命名空间包的主题似乎对于初学者来说有点混乱,并且它的先前版本的Python以几种不同的方式实现它或者StackOverflow上的许多问答都是过时的并没有帮助.我正在寻找Python 3.5
或以后的解决方案.
我正在将一堆Python代码重构为模块和子模块,并且努力使这些项目中的每一个都设置为在坐在同一名称空间中时彼此独立地运行.
我们最终将使用内部PyPi服务器,将这些软件包提供给我们的内部网络,并且不希望将它们与外部(公共)PyPi软件包混淆.
示例: 我有2个模块,我希望能够执行以下操作:
from org.client.client1 import mod1
from org.common import config
Run Code Online (Sandbox Code Playgroud)
反映的模块将分开:
存储库1:
org_client_client1_mod1/
setup.py
mod1/
__init__.py
somefile.py
Run Code Online (Sandbox Code Playgroud)
存储库2:
org_common_config/
setup.py
config/
__init__.py
someotherfile.py
Run Code Online (Sandbox Code Playgroud)
我的Git仓库已经设置为org_client_client1_mod1
和org_common_config
,所以我只需要在包装和执行安装__init__.py
文件,我相信.
随着
__init__.py
,我应该使用哪些(如果有的话)?:Run Code Online (Sandbox Code Playgroud)from pkgutil import extend_path __path__ = extend_path(__path__, __name__)
要么:
Run Code Online (Sandbox Code Playgroud)import pkg_resources pkg_resources.declare_namespace(__name__)
有
setup.py
,我还需要添加namespace_modules
参数,如果是,我会使用namespace_modules=['org.common']
,还是namespace_modules=['org', 'common']
?
我可以通过以某种方式实现这一点而放弃以上所有内容吗?也许是更简单或更"pythonic"的东西?
从分布式的命名空间包中,我知道我可以利用命名空间包将一个大的Python包分成几个较小的包.真的很棒.该文件还提到:
顺便提一下,请注意,在正常的Python包布局中,项目的源树必须包含命名空间包'__init__.py文件(以及任何父包的__init__.py).这些
__init__
.py文件必须包含以下行:Run Code Online (Sandbox Code Playgroud)__import__('pkg_resources').declare_namespace(__name__)
此代码确保命名空间包机制正在运行,并且当前包已注册为命名空间包.
我想知道将相同的目录层次结构保存到包的层次结构有什么好处吗?或者,这只是distribute/setuptools的命名空间包功能的技术要求?
当然,
我想提供一个子包foo.bar,这样我就必须构建以下文件夹层次结构并准备__init__.py以使setup.py工作在命名空间包中:
~foo.bar/
~foo.bar/setup.py
~foo.bar/foo/__init__.py <= one-lined file dedicated to namespace packages
~foo.bar/foo/bar/__init__.py
~foo.bar/foo/bar/foobar.py
Run Code Online (Sandbox Code Playgroud)
我不熟悉命名空间包,但它在我看来1)foo/bar和2)(几乎)单行__init__.py是例行任务.它们提供了一些"这是命名空间包"的提示,但我认为我们已经在setup.py中有这些信息了?
编辑:
如下面的块所示,我可以在我的工作目录中使用没有该嵌套目录和单行__init__.py的命名空间包吗?也就是说,我们可以要求setup.py通过只放一行来自动生成它们namespace_packages = ['foo']
吗?
~foo.bar/
~foo.bar/setup.py
~foo.bar/src/__init__.py <= for bar package
~foo.bar/src/foobar.py
Run Code Online (Sandbox Code Playgroud) 我想在一个主模块中有几个python子模块,但是我想将它们作为单独的python软件包分发。因此,程序包A应该提供“ my_data.source_a”,程序包B应该提供“ my_data.source_b”,等等。
我发现我必须为此使用一个名称空间包,但是试图弄清楚细节,我发现了多个解决该问题的PEP。PEP 420似乎是最新的,它是基于PEP 402和PEP 382建立的。
对我来说,尚不清楚实现的不同PEP的状态。所以我的问题是:http : //pythonhosted.org/distribute/setuptools.html#namespace-packages仍然是解决之道,还是应该如何构建我的命名空间包?
我有一个Python 3.6虚拟环境,其中安装了两个共享一个公共顶层目录的库(除其他外)shared_name
。它不包含__init__.py
。据我了解,那应该是一个隐式命名空间包(PEP 420)
当我PYTHONPATH
在顶层也添加了使用该名称的源模块时,则无法找到后一个目录。当两个shared_name
目录都有一个时__init__.py
,Python也找不到它。添加pkgutils.extend()
到一个或两个__init__.py
文件都无济于事。
结构是这样的:
lib/python3.6/site-packages/shared_name/p1
lib/python3.6/site-packages/shared_name/p2
source_package/shared_name/infrastructure.py
Run Code Online (Sandbox Code Playgroud)
立刻在shared_name
下面没有__init__.py
文件。在运行时,sys.path
包含source_package
,但shared_name.__path__
仅包含lib/python3.6/site-packages/shared_name
,不包含source_package
。
我不知如何调试它或它可能有什么问题。命名空间包是否不允许混合安装和源包?(对我而言,文档对这个主题似乎无语。)使用PYTHONVERBOSE
也无济于事。我不明白为什么
# destroy shared_name
Run Code Online (Sandbox Code Playgroud)
在任何尝试过的证据(更不用说匹配)之前发生。
这个问题跟进在Python中创建命名空间包的方法以及如何在Python中创建命名空间包?.
您不能在命名空间包中包含任何其他代码和数据
__init__.py
.尽管它可能在开发期间或项目作为.egg
文件安装时起作用,但在使用"系统"打包工具安装项目时它将无法工作 - 在这种情况下,__init__.py
文件将不会被安装,更不用说执行了.
这似乎使得无法拥有一个带有独立分布式扩展子包的"主库"包.我想要的是能够:
定义一个核心库包,使用如下:
import mylibrary
mylibrary.some_function()
Run Code Online (Sandbox Code Playgroud)允许库扩展,单独打包和分发,使用如下:
import mylibrary.myextension
mylibrary.myextension.some_other_function()
Run Code Online (Sandbox Code Playgroud)我希望能够使用命名空间包来实现这一点,但基于上面的问题和链接,似乎并非如此.这可以完成吗?
我想知道你想要使用相同基础包的子项目的正确/最简单/最pythonic方式.我们目前有这样的文件结构:
trunk\
proj1\setup.py
company_name\__init__.py + proj1's code
proj2\setup.py
company_name\__init__.py + proj2's code
Run Code Online (Sandbox Code Playgroud)
我们希望保持命名空间company_name对我们所有的项目都是通用的(也许这本身就是unpythonic?)但是当proj1和proj2安装在开发模式下时,第一个安装会被破坏.它看起来import company_name...
很困惑在哪个company_name包中查找它并抓取第一个/最后一个/随机一个.
通常如何在更大的python项目中处理?是否可以通过构建某种巨型蛋的主干中的setup.py来解决这个问题?我没有在谷歌或堆栈上找到任何相关信息,所以任何信息甚至只是链接非常感谢!
编辑:我刚尝试在根文件夹中添加setup.py
...
namespace_packages = ['company_name'],
package_dir = {'company_name' : ['proj1/company_name', 'proj2/company_name']}
...
Run Code Online (Sandbox Code Playgroud)
适当pkg_resources.declare_namespace(__name__)
的__init_.py
文件,但./setup.py bdist_egg
只是给出:
company_name setup命令中的错误:分发包含名称空间包'company_name'的模块或包
我很难构建我的 Python setup.py 文件来做我想做的事。我有一个这样设置的包:
somestuff_root/
setup.py
myutils/
__init__.py
a/
__init__.py
somestuff.py
Run Code Online (Sandbox Code Playgroud)
我有另一个这样的包设置:
otherstuff_root/
setup.py
myutils/
__init__.py
b/
__init__.py
otherstuff.py
Run Code Online (Sandbox Code Playgroud)
所以事情被组织在我的 site-packages/ 目录中,例如:
myutils/
a/
somestuff.py
b/
otherstuff.py
Run Code Online (Sandbox Code Playgroud)
这正是我用 pip 安装它们后想要的。
我的问题是卸载第二个包(使用 pip)也会清除第一个包——这不是我想要发生的。我只想删除 myutils.b 并将 myutils.a 保留在原处。
我怀疑我将多个init .py 文件与 myutils/ 文件夹中的内容混淆了,但我不确定如何使这些文件正常工作。
——
还找到了这个有用的页面:
http://www.sourceweaver.com/musings/posts/python-namespace-packages
我在Python 3.6.0rc1中发现了使用隐式命名空间包的奇怪行为.你能告诉我,如果我错了或是Python 3.6的错误吗?
我正在使用命名空间包marrow
,它有两个独立的包marrow.util
和marrow.mailer
.第二个取决于第一个.
假设我们已经marrow.util
安装site-packages
了Python 2.7,3.5和3.6:
$ ls -la /usr/lib/python*/site-packages/marrow
/usr/lib/python2.7/site-packages/marrow:
total 24
drwxr-xr-x. 3 root root 4096 Dec 23 12:23 .
drwxr-xr-x. 196 root root 16384 Dec 23 12:23 ..
drwxr-xr-x. 3 root root 4096 Dec 23 12:23 util
/usr/lib/python3.5/site-packages/marrow:
total 12
drwxr-xr-x. 3 root root 4096 Dec 23 12:24 .
drwxr-xr-x. 99 root root 4096 Dec 23 12:24 ..
drwxr-xr-x. 4 root root 4096 Dec 23 12:24 util …
Run Code Online (Sandbox Code Playgroud) 我有一组命名空间包,旨在在 python3.6 环境中运行。
它们各自的设置如下:
if sys.version_info < (3, 6):
print("Python versions < 3.6 unsupported", file=sys.stderr)
sys.exit(1)
setup(
name="mynamespace.subpackage",
version=VERSION,
packages=[
"mynamespace.subpackage",
],
package_dir={"": "src"},
package_data={
"": [],
},
include_package_data=True,
zip_safe=False,
install_requires=[
"mynamespace.core", # May have explicit dependencies that are not cyclic
],
namespace_packages=["mynamespace"],
...
)
Run Code Online (Sandbox Code Playgroud)
所有子包都可以很好地并排安装。
当我想通过 获得强大的类型检查时,问题就出现了mypy
。 在源文件上运行时mypy
无法找到子包mynamespace.core
mynamespace.subpackage
子包(例如),这意味着我无法跨子包边界进行可靠的类型检查。
这似乎是一个已知问题: https ://github.com/python/mypy/issues/1645
Guido 提到解决方法是“添加虚拟文件__init__.py
或__init__.pyi
文件”,但他并没有真正详细说明,事实证明这对我来说并不像我希望的那么明显。将这些文件添加到本地存储库允许 mypy 按预期运行本地存储库,我不知道如何访问同级命名空间包中的类型信息。
我的问题是:我将如何修改mynamespace.core
- 以便在安装时mypy
能够在其他模块中获取它的类型信息?
我已经将我的 Python 项目重新组织到同名的保护伞下。我的项目现在可以被视为多个可以相互依赖的子系统。这意味着每个子模块现在都可以单独分发,以便仅安装所需的依赖项。
\n\n旧结构:
\n\n/\n\xe2\x94\x9c\xe2\x94\x80 myproj/\n\xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80 __init__.py\n\xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80 mod1.py\n\xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80 subpackage1/\n\xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80 subpackage2/\n\xe2\x94\x94\xe2\x94\x80 setup.py\n
Run Code Online (Sandbox Code Playgroud)\n\n新结构:
\n\n/\n\xe2\x94\x9c\xe2\x94\x80 myproj/\n\xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80 common/ \n\xe2\x94\x82 \xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80 mod1.py\n\xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80 subpackage1/\n\xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80 subpackage2/\n\xe2\x94\x94\xe2\x94\x80 setup.py\n
Run Code Online (Sandbox Code Playgroud)\n\nmyproj
正如您所看到的,除了现在是命名空间包和子包之外,没有太大变化common
,subpackage1
并且subpackage2
现在可以独立分发。
有没有可能,仍然保留一个独一无二的setup.py
文件的情况下创建 3 个独立的包?
myproj.common
myproj.subpackage1
myproj.subpackage2
另外我想指定安装时myproj.subpackage1
,myproj.common
是必需的,或者myproj.subpackage2
需要myproj.common
同时myproj.subpackage1
。
我有一个非常简单的名称空间包(内容包括在下面,以及目录布局)。如果尝试导入namespace_repro.module
,则会出现以下错误:AttributeError: module 'namespace_repro' has no attribute 'module'
。据我了解,我的程序包具有有效的布局,导入应该可以进行。有趣的是,该错误仅在Python 3.6.8中存在,并且导入在Python 3.7中成功。
我有一个新的目录import-error-repro
,在它setup.py
(见下文),然后一个嵌套的目录路径src/namespace_repro/module
,包含三个文件__init__.py
,x.py
和y.py
。它们的内容:
setup.py
from setuptools import find_namespace_packages, setup
setup(
name='namespace-repro',
version='0.1.0',
python_requires='>=3.6',
packages=find_namespace_packages('src'),
package_dir={'': 'src'},
zip_safe=False,
)
Run Code Online (Sandbox Code Playgroud)
src/namespace_repro/module/__init__.py
:
from namespace_repro.module.x import x
Run Code Online (Sandbox Code Playgroud)
src/namespace_repro/module/x.py
:
import namespace_repro.module.y as y
x = y.y
Run Code Online (Sandbox Code Playgroud)
最后src/namespace_repro/module/y.py
:
y = True
Run Code Online (Sandbox Code Playgroud)
我通过创建了一个全新的Python 3.6 conda环境conda create -n namespace6 python=3.6 ipython
,然后将其激活并安装了软件包pip install -e ./import-error-repro
(请注意, …
我阅读了文档和相当多的 stackoverflow 帖子,但没有找到明确的答案来解决我的疑问。
我想我明白命名空间包的用途。
我只对 Python>=3.3 和隐式命名空间包感兴趣 - 没有__init__.py
.
命名空间包是否应该只包含其他包,或者模块(即.py
文件)也“允许”?
命名空间包是否应该仅用作“容器”包,或者它们也可以包含在常规包中吗?
如果命名空间包只作为容器有意义,我想我可以声明,每当我有一个真正的包文件夹时,它的所有包含 python 模块的子文件夹也应该有__init__.py
?
# this is fine
ns_package/
+-- real_package/
+-- __init.py__
# how about this?
real_package/
+-- __init.py__ # I have it for docs AND want to force the dir to be a real package
+-- ns_package/ # I would just like to avoid an empty __init__.py
+-- amodule.py
Run Code Online (Sandbox Code Playgroud)
我怀疑名称空间包仅作为容器才有意义,因为在其他情况下,我将无法使用不同路径中的其他内容扩展名称空间,因为父级是一个真正的包,必须在单个点中定义文件系统。因此我不会获得命名空间包的主要优势。
我问这个问题是因为在运行和导入模块(从项目的根目录)时,常规包内包含隐式名称空间包的情况工作得非常好。然而,它需要对安装的设置脚本进行一些调整,我想知道我一开始是否做了一些有缺陷的事情。
注意:我尝试使用隐式命名空间包主要不是因为我想利用它们的功能,而是因为我讨厌空 …
Python 具有创建命名空间包的能力。如何获取命名空间下已安装软件包的列表?
即类似:
import namespace_package
dir(namespace_pageage)
Run Code Online (Sandbox Code Playgroud) python ×13
setuptools ×6
python-3.x ×5
package ×3
distutils ×1
mypy ×1
namespaces ×1
pypi ×1
python-3.6 ×1
setup.py ×1