2016-03-21 75 views
2

有導入此包時一個明顯的週期性導入錯誤:爲什麼週期性的進口問題消失了?

文件__init__.py

from . import modules 

文件forward.py

from .modules import ext_modules 

def forward(dest): 
    if dest in ext_modules: 
     print("forwarding to {}".format(ext_modules[dest])) 

文件modules.py

from . import forward 

ext_modules = {} 

def main(): 
    ext_modules['test'] = 'TEST' 
    forward.forward('test') 

這進口問題可以解決,例如通過交換modules.py文件中的第1行和第3行。到目前爲止,我想我明白髮生了什麼事情。

我真的不明白的是這個。當我將另一個導入添加到__init__.py文件的頂部時:

from . import forward 
from . import modules 

問題消失了。該軟件包可以導入,主要功能可以工作。然而,modulesforward之間的週期依賴性仍然存在。這些文件保持不變。你能解釋一下那裏發生了什麼嗎? (Python版本3.5)

回答

1

當您導入模塊,這種情況發生的第一件事情,是一個module對象添加到sys.modules映射。隨後的import針對同一模塊的語句將重新使用該對象,而不是將該文件加載到內存中。

然後Python繼續執行模塊內容並將生成的全局名稱添加到module對象中。

在你的情況下,重要的是你的模塊導入訂單forward直接取決於模塊內容的modules,而modules僅取決於模塊forward上存在,而不是模塊的內容(參考forward.forward依賴性被推遲,直到main()被調用)。

所以如果forward首先進口,空forwardmodule對象被創建,第一行from .modules import ext_modules被執行時,觸發所述modules.py文件被加載,然後可以安全使用from . import forward因爲module對象現在存在。然後modules.py文件的其餘部分可以繼續運行而不會發生進一步的事件。

但是,如果導入modules第一,那麼就沒有forwardmodule對象還沒有,所以後來的forward.py文件第二運行,而且由於modulesmodule對象仍然是空的,沒有ext_modules屬性from .modules import ext_modules線失敗。

+0

感謝您的詳細解釋。我巧妙地發現了它。我不知道如何調用它。也許是「空模塊技巧」?無論如何,你會推薦使用它作爲週期性依賴問題的一個可能的解決方案,還是它是一個醜陋的黑客? – VPfB

+1

@ VPfB:這是解決您的問題的合適解決方案。你可以通過使用from來改進它。在'forward.py'中導入模塊,然後在'forward(dest)'模塊中使用'modules.ext_modules';即到處使用晚期綁定。 –