我想知道的是,
__package__
到底是什么意思?在官方文档和 Stack Overflow 上都没有找到解释。如果您能提供一些示例,我会非常高兴。__package__
到底是什么意思?在官方文档和 Stack Overflow 上都没有找到解释。如果您能提供一些示例,我会非常高兴。__package__
。如果存在此属性,则相对导入将基于此属性,而不是模块 __name__
属性。__package__
属性应该被设置。它的值必须是一个字符串,但可以与其__name__
的值相同。如果该属性设置为None
或缺失,则导入系统会使用更合适的值进行填充。当模块是一个包时,其__package__
值应该被设置为其__name__
。当模块不是一个包时,对于顶级模块,__package__
应该被设置为空字符串,对于子模块,应该设置为父包的名称。详见PEP 366。foo/bar/baz.py
的模块,__name__
被设置为foo.bar.baz
,__package__
被设置为foo.bar
,而foo/bar/__init__.py
将对__name__
和__package__
属性都设置为foo.bar
。我只想知道
__package__
到底是什么意思
__package__
是使显式相对导入成为可能的机制。
__package__
有三种可能的取值:
也就是说,如果一个模块在一个包中,__package__
将被设置为包名以启用显式相对导入。具体来说:
当模块是一个包时,应该将其
__package__
值设置为其__name__
。当模块不是一个包时,__package__
应该被设置为[...]对于子模块,则是父包的名称。
如果一个模块在根目录或顶级目录下,即当前模块是使用
import current_module
或者当一个顶层模块被作为入口点运行时,例如:
$ python -m current_module
那么如果模块不是一个包,__package__
将会是空字符串。或者如文档所说:
当模块不是一个包时,
__package__
应该对于顶层模块被设置为空字符串...
如果一个模块/脚本是通过文件名运行的,__package__
为 None:
当主模块通过它的文件名指定时,
__package__
属性将会被设置成None。
首先,让我们使用Python 3.6创建一个带有嘈杂调试信息的文件结构:
text = "print(f'{__name__}, __file__: {__file__}, __package__: {repr(__package__)}')"
from pathlib import Path
Path('foo.py').write_text(text)
Path('package').mkdir()
Path('package/__init__.py').write_text(text)
Path('package/__main__.py').write_text(text)
Path('package/bar.py').write_text(text)
# and include a submodule with a relative import:
Path('package/baz.py').write_text(text + '\nfrom . import bar')
现在我们可以看到,作为模块执行的 foo.py 的 __package__
为空字符串,而以文件名为入口点执行的脚本却是 None
:
$ python -m foo
__main__, __file__: ~\foo.py, __package__: ''
$ python foo.py
__main__, __file__: foo.py, __package__: None
当我们将一个包作为入口点执行时,它的 __init__.py
模块会运行,然后它的 __main__.py
会运行:
$ python -m package
package, __file__: ~\package\__init__.py, __package__: 'package'
__main__, __file__: ~\package\__main__.py, __package__: 'package'
同样地,当我们将一个子模块作为入口点执行为模块时,__init__.py
模块会运行,然后它运行:
$ python -m package.bar
package, __file__: ~\package\__init__.py, __package__: 'package'
__main__, __file__: ~\package\bar.py, __package__: 'package'
最后,我们看到显式相对导入,也就是拥有__package__
的全部原因(在这里发生的最后一步)被启用:
$ python -m package.baz
package, __file__: ~\package\__init__.py, __package__: 'package'
__main__, __file__: ~\package\baz.py, __package__: 'package'
package.bar, __file__: ~\package\bar.py, __package__: 'package'
注意,在输出中,我已经用~
代替了父目录。
python package
。在这种情况下,__package__
是''而不是None
。但我不知道为什么会做出这个选择。 - figs_and_nuts
__package__
属性真正有用呢? - chiffapython /modulename.py
),并针对该情况进行调整。 - Martijn Pieters__name__.rpartition('.')[0]
行的默认行为对我来说并不完全清晰,就像__name__
和__package__
属性的交互以及用于从项目中的其他文件夹导入模块的基本路径一样。实际上,我有一个可以访问主入口点的模块行为,而且我很满意,我不想破坏它,但我也想使用深层文件夹树中的模块作为某些应用程序的主要访问点,这是我目前遇到的问题。 - chiffastr.rpartition()
调用会在最后一个.
上分割并返回前半部分;因此foo.bar.baz.eggs
分割成了foo.bar.baz
。其余内容太广泛,无法在注释中详细说明。 - Martijn Pieters