我使用的是Python 3.5.1。我阅读了文档和软件包部分:https://docs.python.org/3/tutorial/modules.html#packages
现在,我有以下结构:
/home/wujek/Playground/a/b/module.py
module.py:
class Foo:
def __init__(self):
print('initializing Foo')
现在,在/home/wujek/Playground中:
~/Playground $ python3
>>> import a.b.module
>>> a.b.module.Foo()
initializing Foo
<a.b.module.Foo object at 0x100a8f0b8>
类似地,现在在home, Playground的超级文件夹中:
~ $ PYTHONPATH=Playground python3
>>> import a.b.module
>>> a.b.module.Foo()
initializing Foo
<a.b.module.Foo object at 0x10a5fee10>
事实上,我可以做各种各样的事情:
~ $ PYTHONPATH=Playground python3
>>> import a
>>> import a.b
>>> import Playground.a.b
为什么会这样?我虽然需要__init__.py文件(空的会工作)在a和b模块.py导入时,Python路径指向游乐场文件夹?
这似乎是从Python 2.7开始改变的:
~ $ PYTHONPATH=Playground python
>>> import a
ImportError: No module named a
>>> import a.b
ImportError: No module named a.b
>>> import a.b.module
ImportError: No module named a.b.module
在~/Playground/a和~/Playground/a/b中都有__init__.py,它可以正常工作。
概述
@Mike的回答是正确的,但是太不精确了。确实,Python 3.3+支持隐式命名空间包,允许它在没有__init__.py文件的情况下创建包。这被称为命名空间包,与常规包相反,常规包有__init__.py文件(空或不空)。
但是,只有在需要时才应该创建命名空间包。对于大多数用例和开发人员来说,这并不适用,所以你应该坚持使用EMPTY __init__.py文件。
命名空间包用例
为了演示这两种类型的python包之间的区别,让我们看下面的例子:
google_pubsub/ <- Package 1
google/ <- Namespace package (there is no __init__.py)
cloud/ <- Namespace package (there is no __init__.py)
pubsub/ <- Regular package (with __init__.py)
__init__.py <- Required to make the package a regular package
foo.py
google_storage/ <- Package 2
google/ <- Namespace package (there is no __init__.py)
cloud/ <- Namespace package (there is no __init__.py)
storage/ <- Regular package (with __init__.py)
__init__.py <- Required to make the package a regular package
bar.py
Google_pubsub和google_storage是单独的包,但它们共享相同的名称空间谷歌/cloud。为了共享同一个命名空间,需要将公共路径下的每个目录都设置为命名空间包,即谷歌/和cloud/。这应该是创建名称空间包的唯一用例,否则就不需要它了。
谷歌和谷歌/cloud目录中没有__init__py文件,这一点很重要,这样两个目录都可以解释为命名空间包。在Python 3.3+中,sys. exe目录下的任意目录。名称与正在查找的包名称匹配的路径将被识别为该包的贡献模块和子包。因此,当您同时从google_pubsub和google_storage导入时,Python解释器将能够找到它们。
This is different from regular packages which are self-contained meaning all parts live in the same directory hierarchy. When importing a package and the Python interpreter encounters a subdirectory on the sys.path with an __init__.py file, then it will create a single directory package containing only modules from that directory, rather than finding all appropriately named subdirectories outside that directory. This is perfectly fine for packages that don't want to share a namespace. I highly recommend taking a look at Traps for the Unwary in Python’s Import System to get a better understanding of how Python importing behaves with regular and namespace package and what __init__.py traps to watch out for.
总结
Only skip __init__.py files if you want to create namespace packages. Only create namespace packages if you have different libraries that reside in different locations and you want them each to contribute a subpackage to the parent package, i.e. the namespace package.
Keep on adding empty __init__.py to your directories because 99% of the time you just want to create regular packages. Also, Python tools out there such as mypy and pytest require empty __init__.py files to interpret the code structure accordingly. This can lead to weird errors if not done with care.
资源
我的回答只触及了常规包和名称空间包的工作方式的表面,因此请查看以下资源以获得更多信息:
PEP 420——隐式命名空间包
导入系统-常规包
导入系统-命名空间包
Python导入系统中的粗心陷阱