相对导入不起作用,看起来找不到模块
relative imports doesn't work, looks like can't find the module
我有以下情况,其中 a 是一个目录:
a/
__init__.py
first.py
second.py
__init__.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 已经加载,所以没有错误,它只是跳到 [=中列出的下一个=15=].
这似乎是 Python 导入机制中长期存在的错误。问题在于 a 模块在完全加载之前不会添加到其包的全局命名空间中。如果 module
仅部分加载,这会中断 from package import module
语句。不过,您仍然可以使用 import package.module
,它长期以来一直得到导入系统的特殊支持。
如jonrsharpe commented, the Python developers have been aware of this issue 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 中不会出错)。
我有以下情况,其中 a 是一个目录:
a/
__init__.py
first.py
second.py
__init__.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 已经加载,所以没有错误,它只是跳到 [=中列出的下一个=15=].
这似乎是 Python 导入机制中长期存在的错误。问题在于 a 模块在完全加载之前不会添加到其包的全局命名空间中。如果 module
仅部分加载,这会中断 from package import module
语句。不过,您仍然可以使用 import package.module
,它长期以来一直得到导入系统的特殊支持。
如jonrsharpe commented, the Python developers have been aware of this issue 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 中不会出错)。