2015-07-10 28 views
1

我知道這個問題已經在這裏被無數次的問過了,但是我一直被這個問題困住了很長時間,一直沒有能夠在網上找到解決方案。只導入模塊時的Python導入週期

我有一個導入週期,這裏是堆棧跟蹤:

Traceback (most recent call last): 
    File "openldap_lookup.py", line 2, in <module> 
    import pure.directory_service.ds_lookup as dsl 
    File "/home/myname/purity/tools/pure/directory_service/ds_lookup.py", line 8, in <module> 
    import pure.authorization.auth as auth 
    File "/home/myname/purity/tools/pure/authorization/auth.py", line 16, in <module> 
    import auth_unix as auth_impl 
    File "/home/myname/purity/tools/pure/authorization/auth_unix.py", line 17, in <module> 
    import pure.directory_service.ad_lookup as ad_lookup 
    File "/home/myname/purity/tools/pure/directory_service/ad_lookup.py", line 1, in <module> 
    import pure.authorization.auth as auth 
AttributeError: 'module' object has no attribute 'auth' 

我只導入模塊;我避免了from <module> import <class>from <module> import <method>

我試圖在本地重現錯誤,但python沒有任何抱怨。這些都是本地測試文件:

openldap_lookup.py

import ds_lookup 
def openldap_foo(): 
    print ds_lookup.ds_foo 
print 'openldap_lookup importing ds_lookup' 

ds_lookup.py

import auth as au 
def ds_foo(): 
    print au.auth_foo 
print 'ds_lookup importing auth' 

auth.py

import auth_unix 
def auth_foo(): 
    print auth_unix.auth_unix_foo 
print 'auth importing auth_unix' 

auth_unix.py

import ad_lookup 
def auth_unix_foo(): 
    print ad_lookup.ad_foo 
print 'auth_unix importing ad_lookup' 

ad_lookup.py

import auth as au 
def ad_foo(): 
    print au.auth_foo 
print 'ad_lookup importing auth' 

但是Python不會抱怨:

[email protected]:~/cycletest$ python openldap_lookup.py 
ad_lookup importing auth 
auth_unix importing ad_lookup 
auth importing auth_unix 
ds_lookup importing auth 
openldap_lookup importing ds_lookup 
[email protected]:~/cycletest$ 

我不是一個Python的專家,但據我所知,進口週期導致錯誤。但爲什麼小測試文件不會出現同樣的錯誤?什麼時候Python導入週期合法,什麼時候不是?我能做些什麼來解決這個問題?

我非常感謝來自python專家的任何幫助。


既然很多人都會問,爲什麼我要把這個循環放在第一位呢?

那麼,openldap_lookup和ad_lookup都包含ds_lookup中的基類的子類。 ds_lookup需要來自auth的常量。 auth需要auth_unix作爲實現,而auth_unix又會調用實現openldap_lookup和ad_lookup。

我很想將常量從auth移除並刪除循環,但是這個代碼是一個大的git repo的一部分,其中數百個文件依賴於auth中的常量和方法,我想避免必須如果可能的話,重構他們所有的人。

回答

0

實際上,你不僅僅是導入模塊 - 你是從包中導入模塊,而你的測試用例實際上並不反映這一點。

我認爲問題在於,在第一次導入pure.authorization.auth時,解釋器仍在構建pure.authorization模塊(它尚未將auth綁定到pure.authorization中,因爲它尚未完成導入auth),所以第二次遇到這個時,它找到了pure.authorization模塊,但是它裏面還沒有全局變量auth。

只要打破循環,auth是否真的需要立即導入auth_unix,或者可以推遲到您真的需要auth實現?

+0

'as auth'部分是那裏的問題。刪除它,它會正常工作。 – tynn

+0

你絕對正確的做法是,將最後一個「import pure.authorization.auth as auth」(ad_lookup中的那個)改爲保持錯誤不會在這裏發生,但如果在模塊級需要auth,則可能會稍後發生。例如。導入後緊接着的「auth = pure.authorization.auth」仍然會失敗。但如果認證只能在函數中查找和使用,那麼改變它是一種很好的方法。 –