2012-09-18 51 views
1

我的團隊正在與Django合作開展一個龐大的項目。爲了簡單起見,下面是純Python來說明問題(原始問題有模型和應用程序,而不是類(我知道它們都是類)和包(我知道它們都是包)。用Python導入的無限循環;尋找Pythonic方式

a.py

from b import B1 


class A1(object): 
    def __init__(self): 
     print "object A1" 


class A2(object): 
    def __init__(self): 
     print "object A2" 


A1() 
B1() 

b.py

from a import A2 


class B1(object): 
    def __init__(self): 
     print "object B1" 


A2() 

a.py被調用時,它試圖從b導入B1另一方面,該包裝試圖導入A2a包,然後,從開始,這將永遠重複。蟒蛇說:

[[email protected] recursion]$ python2 a.py 
Traceback (most recent call last): 
    File "a.py", line 1, in <module> 
    from b import B1 
    File "/home/dagrevis/Python/recursion/b.py", line 1, in <module> 
    from a import A2 
    File "/home/dagrevis/Python/recursion/a.py", line 1, in <module> 
    from b import B1 
ImportError: cannot import name B1 

解決的辦法之一就是讓每個對象一個文件。就像C++或Java一樣。然後我想起了Guido對Python的看法:「不要在Python中編寫Java(或C++,或Javascript,...)」。是否有更多的Pythonic方法來解決這個問題?

謝謝你的任何建議!

+2

這裏是一些背景信息:[Python:Circular(or cyclic)imports](http://stackoverflow.com/q/744373/222914) –

+0

可能的重複[Import Error。循環參考](http://stackoverflow.com/questions/11028711/import-error-circular-references) – mgilson

回答

3

您的用例不是「可解決的」。您可以將ImportError轉換爲導入模塊a(和b)而不是導入對象的AttributeError,但這不會改變您無法使用這些模塊的事實。

問題在於您的模塊a需要在導入之前完全執行b,還需要b請求a在導入之前完全執行。

這是根本不可能解決的,它是需要一個重構一個明確的症狀:您的ab模塊應該是一個單獨的模塊(或者你可能需要做一些更深層次的重構)。

編輯: 實際上,您可能可以解決這個問題,即使我認爲這樣做相當難看,在需要時將導入放在文件末尾。 但我認爲這只是一個更大的問題的補丁。

+0

你的答案比我的更清晰,更準確,我會刪除我的。 – jleahy

1

您的示例過於簡化 - 它不能解釋爲什麼週期性導入是必要的。但無論如何,在這裏是把它重構爲可運行代碼的一種方法:

a.py:

class A1(object): 
    def __init__(self): 
     print "object A1" 


class A2(object): 
    def __init__(self): 
     print "object A2" 

b.py:

class B1(object): 
    def __init__(self): 
     print "object B1" 

c.py:

from a import A1, A2 
from b import B1 

A1() 
A2() 
B1()