lum*_*ric 5 python python-import python-3.x relative-import
下面这行代码在 Python 3 中起什么作用?
>>> from . import *
Run Code Online (Sandbox Code Playgroud)
它不输出任何内容,我在 Python 3.7.3 中看到的唯一变化如下:
>>> '__warningregistry__' in locals()
False
>>> from . import *
>>> '__warningregistry__' in locals()
True
>>> locals()['__warningregistry__']
{'version': 0}
Run Code Online (Sandbox Code Playgroud)
这可能是警告模块的一部分,表示在某处有一个未打印的警告,但文档仅提到了模块中的一个变量 。__warningregistry__
warnings
该文档解释了如何from . import foo
工作以及如何from bar import *
工作,但我找不到任何有关from . import *
. 人们可能期望所有名称都__init__.py
加载到当前名称空间中(就像from bla import *
一样bla.py
),但情况似乎并非如此,而且在__name__ == '__main__'
(脚本和终端)时也没有意义。
Python 2 的行为与我的预期更加相似:
>>> # Python 2.7.16
>>> from . import *
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: Attempted relative import in non-package
Run Code Online (Sandbox Code Playgroud)
PEP 328很有启发性,但也没有回答我的问题。
当__main__
是脚本或交互式会话时,.
是__main__
包本身:
$ python3 -c 'from . import float'
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: cannot import name 'float' from '__main__' (unknown location)
Run Code Online (Sandbox Code Playgroud)
这造成了from . import *
麻烦,并__warningregistry__
增加了机器的副作用import
。
相对导入由PEP 366__main__
进行特殊处理。这引入了相对包名查找,并指定具有特殊值。__package__
__main__. __package__
None
此外,模块导入规范__main__.__spec__
可能是None
- 即在交互式 shell 中或在执行脚本时。
事实证明,任何带有 的模块__package__ = __spec__ = None
都会将其视为.
自身:
$ cat test.py
__package__ = __spec__ = None
from . import float
$ python3 -c 'import test'
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/Users/mfischer/PycharmProjects/lispy/test.py", line 2, in <module>
from . import float
ImportError: cannot import name 'float' from 'test' (./test.py)
Run Code Online (Sandbox Code Playgroud)
添加__warningregistry__
是因为缺少属性存在隐藏警告。默认情况下它是被抑制的,但是您可以在启用所有警告的情况下看到它:
$ python3 -Wa -c 'from . import float'
-c:1: ImportWarning: can't resolve package from __spec__ or __package__, falling back on __name__ and __path__
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: cannot import name 'float' from '__main__' (unknown location)
Run Code Online (Sandbox Code Playgroud)