2010-09-17 70 views
0

循環依賴我有三個文件:如何解決進口

testimports模塊:

#import moduleTwo 
import moduleOne 

hiString = "Hi!" 

moduleOne.sayHi() 

ModuleOne的:

import moduleTwo 

class sayHi(): 
    moduleTwo.printHi() 

ModuleTWO中:

import testimports 

def printHi(): 
    print(testimports.hiString) 

如果我運行testimports,我得到:

Traceback (most recent call last): 
    File "..file path snipped../testimports/src/testimports.py", line 2, in <module> 
    import moduleOne 
    File "..file path snipped../testimports/src/moduleOne.py", line 1, in <module> 
    import moduleTwo 
    File "..file path snipped../testimports/src/moduleTwo.py", line 1, in <module> 
    import testimports 
    File "..file path snipped../testimports/src/testimports.py", line 6, in <module> 
    moduleOne.sayHi() 
AttributeError: 'module' object has no attribute 'sayHi' 

但是,如果我去掉了import moduleTwotestimports,該方案得到了這一點它停止工作之前:

Traceback (most recent call last): 
    File "..file path snipped../testimports/src/testimports.py", line 1, in <module> 
    import moduleTwo 
    File "..file path snipped../testimports/src/moduleTwo.py", line 1, in <module> 
    import testimports 
    File "..file path snipped../testimports/src/testimports.py", line 2, in <module> 
    import moduleOne 
    File "..file path snipped../testimports/src/moduleOne.py", line 3, in <module> 
    class sayHi(): 
    File "..file path snipped../testimports/src/moduleOne.py", line 4, in sayHi 
    moduleTwo.printHi() 
AttributeError: 'module' object has no attribute 'printHi' 

我如何去解決這個圓依賴性問題?

+1

請搜索SO進行循環導入。有幾百個問題就像你的問題。 http://stackoverflow.com/search?q=%5Bpython%5D+circular+import – 2010-09-18 12:58:22

+1

可能重複的[Python:Cyclic imports](http://stackoverflow.com/questions/744373/python-cyclic-imports) – 2010-09-18 12:58:46

回答

2

重寫testimports.py可以幫助:

import moduleOne 

hiString = "Hi!" 

def main(): 
    moduleOne.sayHi() 

if __name__ == "__main__": 
    main() 
+0

謝謝!有效! :D – wrongusername 2010-09-17 23:20:59

2

你的問題是,當Python導入東西處執行的基本級別的所有語句。 hiString被重新分配,並且當Module3將原始testimports.py作爲模塊導入時再次進行調用。 Anatoly Rr的解決方案是可行的,因爲這個調用現在在def中。 def未被調用,因爲__name__向Python運行時指示正在導入模塊。從命令行調用時,模塊名稱爲__main__

+0

實際上並不準確。例如,hiString不會再次分配,但會有兩個hiStrings。在這兩種情況下,除了導入的testimports之外,還會有一個__ _ main _ \ _。詳情請參閱我的回答。 – 2010-09-18 01:06:47

9

verisimilidude是沿着正確的方向。我會擴大一點,以提供更多細節。

在這兩種情況下,這是發生了什麼:

  1. testimports__main__
  2. testimports進口moduleOne執行。現在從文件中讀取moduleOne並將其添加到導入模塊列表sys.modules
  3. 執行導入moduleOne首先導入moduleTwo。現在從文件中讀取moduleTwo並將其添加到導入模塊列表sys.modules。請注意,在此階段,moduleOne的其餘部分尚未執行,因此sayHi未定義。
  4. 現在moduleTwo通過導入testimports開始執行。這是第一次導入testimports,與__main__相同。它現在插入到sys.modules
  5. 這裏是事情變得有趣的地方。新進口testimports進口moduleOnemoduleOne已在sys.modules,所以它不會再讀取。然後執行進展到行moduleOne.sayHi()moduleOne的導入尚未完成,sayHi尚未定義。因此我們得到錯誤。

如果取消註釋moduleTwo,則會發生類似的循環。實質上,__main__進口moduleTwo,其中進口testimports通過進口moduleTwo已進口和進口moduleOne;後者依次導入moduleTwo,然後嘗試呼叫尚未定義的moduleTwo.printHi,因爲moduleTwo尚未完成執行。

Anatoly Rr的解決方案通過使模塊testimports在導入時不調用任何其他模塊功能來打破這一切。所以當它通過moduleTwo導入時,它不會調用moduleOne.sayHi。只有在__main__啓動時纔會執行,以便在所有導入之後延遲執行。

故事的寓意是什麼? Avoid circular dependencies in Python if possible