Python中命名空间包的相对位置和内容>;=3.3
我阅读了文档和一些stackoverflow帖子,但没有找到一个明确的答案来回答我的疑问 我想我理解名称空间包的用途 我只对Python>=3.3和隐式名称空间包感兴趣——没有Python中命名空间包的相对位置和内容>;=3.3,python,python-3.x,python-packaging,namespace-package,Python,Python 3.x,Python Packaging,Namespace Package,我阅读了文档和一些stackoverflow帖子,但没有找到一个明确的答案来回答我的疑问 我想我理解名称空间包的用途 我只对Python>=3.3和隐式名称空间包感兴趣——没有\uuuu init\uuuu.py的文件夹 问题 名称空间包是否应该只包含其他包,或者模块(即.py文件)也是“允许的” 名称空间包应该仅用作“容器”包,还是也可以包含在常规包中 如果名称空间包仅作为容器,我想我可以声明,每当我有一个真正的包文件夹时,它包含python模块的所有子文件夹也应该有\uuu init\u
\uuuu init\uuuu.py
的文件夹
问题
.py
文件)也是“允许的”
\uuu init\uuuuuuuuuupy
#这很好
ns_包/
+--real_软件包/
+--_uuinit.py__
#这个怎么样?
real_软件包/
+--_u init.py__#我将其用于文档,并希望强制目录成为一个真正的包
+--ns_package/#我只想避免使用空的uu init_uuu.py
+--amodule.py
我怀疑名称空间包仅作为容器才有意义,因为在另一种情况下,我将无法使用不同路径中的其他内容扩展名称空间,因为父级是必须在文件系统的单个点中定义的真实包。因此,我无法获得名称空间包的主要优势
上下文
我这样问是因为在运行和导入模块(从项目的根)时,在常规包中使用隐式名称空间包的情况非常好。然而,它需要对安装脚本进行一些调整,我想知道我是否首先做了一些有缺陷的事情
注意:我尝试使用隐式名称空间包主要不是因为我想利用它们的特性,而是因为我讨厌空的
\uuuu init\uuuuu.py
文件。我最初认为Python3.3最终摆脱了这个问题,包不再需要\uuuu init\uuuu.py
,但它似乎并没有那么简单…首先:您使用名称空间包的动机是有缺陷的。空的\uuuu init\uuuu.py
文件没有问题;它们现在可能是空的,但以后可以用内容填充。即使他们一直空着也不会引起任何麻烦
话虽如此,从技术上讲,将名称空间包放在常规包中并没有错。当执行表单导入时,import a.b.c
将分别解析每个组件,b
可以是位于常规包a
中的命名空间包。考虑下面的目录布局:
.
└── a
├── b
│ └── c.py
└── __init__.py
.
├── dir1
│ └── parent
│ ├── child
│ │ ├── one.py
│ ├── __init__.py
├── dir2
│ └── parent
│ ├── child
│ │ └── two.py
│ └── __init__.py
└── main.py
.
└── a
├── b
│ ├── c
│ │ └── three.py
│ └── two.py
└── one.py
然后可以导入模块c
:
>>> import a.b.c
>>> a
<module 'a' from '/tmp/a/__init__.py'>
>>> a.b
<module 'a.b' (namespace)>
>>> a.b.c
<module 'a.b.c' from '/tmp/a/b/c.py'>
有两个命名空间包dir1/parent/child
和dir2/parent/child
。但是,您只能使用其中一个,因为常规包dir1/parent
阻止访问另一个。让我们为main.py
尝试以下内容:
导入系统
扩展(('dir1','dir1'))
导入parent.child.one#这很有效
打印(系统模块['parent'])
打印(系统模块['parent.child'])
打印(系统模块['parent.child.one'])
导入parent.child.two#此操作失败
我们将得到以下输出:
<module 'parent' from 'dir1/parent/__init__.py'>
<module 'parent.child' (namespace)>
<module 'parent.child.one' from 'dir1/parent/child/one.py'>
Traceback (most recent call last):
File "main.py", line 11, in <module>
import parent.child.two
ModuleNotFoundError: No module named 'parent.child.two'
您可以导入任何命名空间包中的任何模块:
>>> import a.one
>>> import a.b.two
>>> import a.b.c.three
>>> a.b.c
<module 'a.b.c' (namespace)>
>导入一个
>>>进口a.b.2
>>>进口a.b.c.3
>>>a.b.c
2)如上所述,您可以将名称空间包放在常规包中,但这没有多大意义,因为它阻止了它们的预期用途
3)这在很大程度上取决于你所说的“应该”是什么意思。从技术上讲,\uuuuu init\uuuuu.py
不是必需的,但它确实很有意义
正如一开始所指出的,
\uuuu init\uuuuu.py
文件的用途不仅仅是指示常规python包,而且它们通常也会被内容填充。如果没有,这没什么好担心的。谢谢你的回答。我知道empty\uuuu init\uuuu.py
是完全无害的,在文件系统中看到它们会让我感到不安,但这不是一个技术参数:)。1) 很好,这就是我自己已经在做的。我只是在文档中没有直接在名称空间包中看到模块的示例,所以我想知道。2) 我明白,这正是我所怀疑的(见我原来的问题);我在找一份确认书:)。3) 因为2),所以我总是将\uuuu init\uuu
放在真实软件包的子文件夹中,以避免混淆。