在Python 3中“ from dot import asterisk”起什么作用?

时间:2019-09-03 14:54:00

标签: python python-3.x python-import relative-import

问题

以下行在Python 3中是做什么的?

>>> from . import *

我到目前为止发现的东西...

它不输出任何内容,而我在Python 3.7.3中可以看到的唯一变化如下:

>>> '__warningregistry__' in locals()
False
>>> from . import *
>>> '__warningregistry__' in locals()
True
>>> locals()['__warningregistry__']
{'version': 0}

这可能是警告模块的一部分,它表明某个警告未打印,但模块__warningregistry__中的documentation mentions only a variable warnings

文档解释了from . import foo works的方式以及from bar import * works的方式,但是我找不到关于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

PEP 328颇具启发性,但也无法回答我的问题。

1 个答案:

答案 0 :(得分:4)

如果__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)

这使from . import *暂时没有了,并添加了__warningregistry__作为import机制的副作用。


PEP 366对来自__main__的相对导入进行了特殊设置。引入__package__进行相对包名称查找,指定__main__. __package__具有特殊值None

此外,模块导入规范__main__.__spec__ may be None-即在交互式外壳中或在执行脚本时。

事实证明,带有__package__ = __spec__ = None any 模块会将.视为自身:

$ 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)

__warningregistry__ is added,因为有一个hidden warning from the missing attributes。默认情况下,它是不显示的,但是您可以使用all warning enabled看到它:

$ 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)