我查看了 asyncio 包的__init__.py
文件(在 Python 3.4.1 中)并偶然发现了最后几行:
"""The asyncio package, tracking PEP 3156."""
import sys
# The selectors module is in the stdlib in Python 3.4 but not in 3.3.
# Do this first, so the other submodules can use "from . import selectors".
# Prefer asyncio/selectors.py over the stdlib one, as ours may be newer.
try:
from . import selectors
except ImportError:
import selectors # Will also be exported.
if sys.platform == 'win32':
# Similar thing for _overlapped.
try:
from . import _overlapped
except ImportError:
import _overlapped # Will also be exported.
# This relies on each of the submodules having an __all__ variable.
from .events import *
from .futures import *
from .locks import *
from .protocols import *
from .queues import *
from .streams import *
from .subprocess import *
from .tasks import *
from .transports import *
if sys.platform == 'win32': # pragma: no cover
from .windows_events import *
else:
from .unix_events import * # pragma: no cover
__all__ = (events.__all__ +
futures.__all__ +
locks.__all__ +
protocols.__all__ +
queues.__all__ +
streams.__all__ +
subprocess.__all__ +
tasks.__all__ +
transports.__all__)
考虑到上面的陈述,当这些名称实际上甚至不应该存在时,他们怎么可能访问events
所有其他子模块(及其各自的变量)?据我所见,标准库的目录不是其中的一部分,子模块本身也没有定义变量。__all__
from … import *
asyncio/
sys.path
submodule.__all__
附带说明:通过查看__init__.py
文件,我真正想知道的是如何将所有子模块的名称自动添加到__all__
我的包列表中,__init__.py
而不是仅仅重复所有这些名称(因为它在几个标准库的其他包)。我目前的方法如下——也许你的答案会揭示这个asyncio
包是如何成功实现这个看起来更像 Python 的把戏的。
from submodule1 import * # does not import __all__
from submodule1 import __all__ as submodule1_all
from submodule2 import *
from submodule2 import __all__ as submodule2_all
__all__ = submodule1_all + submodule2_all