2016-02-19 107 views
1

我在嘗試導入破碎包兩次時發現了一個奇怪的行爲。讓我們考慮下面的包:嘗試導入破損包兩次時出現錯誤導入錯誤

| 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

究竟發生了什麼?

回答

2

第一次,package.module1被導入,並從此存在於sys.modules。但是,由於package.module2上的導入錯誤,導入package本身不成功,所以package不會在sys.modules中結束。

第二次嘗試導入package將不同地處理導入package.module1,因爲它已存在於sys.modules中。此時的代碼路徑假設某些時候,如果sys.modules中存在名稱爲虛線的模塊,則所有父母都會這樣做。然而,這種假設在第一次嘗試失敗導入package後未能實現。

簡而言之,導入一個可能導致導入更多程序包和模塊的程序包在填充sys.modules時並不是原子性的,而Python最高達到3.4則提出了一些需要原子性的假設。