我有以下情况,其中 a 是一个目录:
a/
__init__.py
first.py
second.py
__初始化__。PY
print('i\'m starting the directory')
__all__ = ['second', 'first']
first.py
print('hi, i\'m the first')
from . import *
second.py
print('hi, i\'m the second')
所以当我从交互式提示符运行时:
>>> import a.first
i'm starting the directory
hi, i'm the first
hi, i'm the second
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/antox/Scrivania/a/first.py", line 2, in <module>
from . import *
AttributeError: 'module' object has no attribute 'first'
为什么找不到 first.py 模块?我的意思是我希望没有错误;在导入运行期间,我认为可以看到 first.py 已经加载,因此没有错误,它只是跳到__all__
中列出的下一个。
答案 0 :(得分:3)
这似乎是Python导入机制中一个长期存在的错误。问题是a模块在完全加载之后才会添加到其包的全局命名空间中。如果from package import module
仅部分加载,则会中断module
语句。你仍然可以使用import package.module
,但很长一段时间都有来自导入系统的特殊支持。
正如jonrsharpe所述,Python开发人员已经意识到了这个问题since 2004。由于只有在包含模块的循环导入时出现问题,并且循环导入通常被认为是不好的设计,因此他们没有把重点放在修复它上面。
然而,最近有进展!几个月前添加了A partial fix,用于Python 3.5,它刚刚发布了第一个alpha版本(完整版本定于9月发布)。该修补程序在加载时仍然不会module
实际添加package
,而是对from package import module
语句添加额外的检查,以便它们无论如何都能在以前引发的循环导入情况下工作ImportError
。
但这并不能解决from package import *
案例。通配符导入的代码显然仍然希望package.__all__
中的所有名称实际存在于模块本身中。它似乎没有检查sys.modules
字典以检查仍在加载过程中的模块。
那么,这对您的代码意味着什么?我认为有两个重要的教训:首先,如果你可以帮助它,不要使用循环导入(而是尝试将两个模块中的一些代码分解为第三个实用程序模块)。其次,不要使用通配符导入(如果使用first.py
from . import first, second
,则在Python 3.5中没有错误。)