简体   繁体   English

在Python 3中,“从点导入星号”做了什么?

[英]What does 'from dot import asterisk' do in Python 3?

Question

What does the following line do in Python 3? 以下几行在Python 3中有什么作用?

>>> from . import *

What I found out so far... 到目前为止我发现了什么......

It does not output anything and the only change I can see in Python 3.7.3 is the following: 它没有输出任何内容,我在Python 3.7.3中看到的唯一变化如下:

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

This might be part of the warnings module and indicates that there is a warning somewhere which is not printed, but the documentation mentions only a variable __warningregistry__ in the the module warnings . 这可能是警告模块的一部分,并指示某个地方没有打印警告,但文档中仅提到模块warnings 的变量 __warningregistry__

The documentation explains how from . import foo 文档解释了如何from . import foo from . import foo works , and how from bar import * works , but I couldn't find anything about from . import * from . import foo 有效 ,以及from bar import *如何工作 ,但是我找不到任何关于from . import * from . import * . from . import * One might expect that all names from __init__.py are loaded into the current name space (as from bla import * would do for bla.py ) but this doesn't seem to be the case and also it doesn't make sense when __name__ == '__main__' (scripts and terminal). 有人可能会认为__init__.py中的所有名称都被加载到当前名称空间中( from bla import *就会用于bla.py )但是这似乎不是这种情况,并且当__name__ == '__main__'时也没有意义。 __name__ == '__main__' (脚本和终端)。

Python 2 behaves more similar to what I had expected: 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 is quite illuminative but doesn't answer my question either. PEP 328非常有启发性,但也没有回答我的问题。

When __main__ is a script or interactive session, . __main__是脚本或交互式会话时, . is the __main__ package itself: __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)

This makes from . import * 这使得from . import * from . import * a noop, with __warningregistry__ added as a side-effect of the import machinery. from . import * a noop,添加__warningregistry__作为import机械的副作用。


Relative imports from __main__ were special-cased by PEP 366 . 来自__main__相对进口是由PEP 366特别提供的。 This introduced __package__ for relative package name lookup, and specifies that __main__. __package__ 这为相对包名称查找引入了__package__指定了__main__. __package__ __main__. __package__ has the special value None . __main__. __package__具有特殊值None

In addition, the module import spec __main__.__spec__ may be None - namely in an interactive shell or when executing a script. 此外,模块导入规范__main__.__spec__可能是None - 即在交互式shell中或执行脚本时。

As it turns out, any module with __package__ = __spec__ = None will treat . 事实证明, 任何带有__package__ = __spec__ = None模块都会处理. as itself: 本身:

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

The __warningregistry__ is added because there is a hidden warning from the missing attributes . 添加了__warningregistry__因为缺少的属性存在隐藏警告 It is suppressed by default, but you can see it with 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM