尝试两次导入损坏的包时错误的ImportError

时间:2016-02-19 13:38:11

标签: python python-3.x

我在尝试两次导入损坏的包时发现了一种奇怪的行为。我们来考虑以下方案:

| package
|--| __init__.py
|--| module1.py

module1.py为空且__init__.py包含:

from package import module1
from package import module2

首次尝试导入package时,会引发ImportError,因为module2缺失:

>>> import package
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/tmp/package/__init__.py", line 2, in <module>
    from package import module2
ImportError: cannot import name 'module2'

但是在第二次尝试时,ImportError抱怨module1

>>> import package
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/tmp/package/__init__.py", line 1, in <module>
    from package import module1
ImportError: cannot import name 'module1'

即使module1之前已成功导入。它甚至可以在sys.modules中使用:

>>> import sys
>>> sys.modules["package.module1"]
<module 'package.module1' from '/tmp/package/module1.py'>

然而,这似乎在Python 3.5中得到修复,可能是因为circular imports involving relative imports are now supported

到底发生了什么?

1 个答案:

答案 0 :(得分:2)

第一次导入package.module1,然后导入sys.modules。但是,由于package.module2上的导入错误,导致package本身并未成功,因此,package不会以sys.modules结尾。

导入package的第二次尝试将以package.module1中已有的方式处理sys.modules的导入。这次的代码路径在某些时候假设如果sys.modules中存在带有虚线名称的模块,那么所有父母也会这样做。但是,在首次尝试导入package失败后,此假设未得到满足。

简而言之,导入一个可能导致更多包和模块被导入的包,对于填充sys.modules而言并不是原子的,而高达3.4的Python做了一些需要原子性的假设。