2010-09-19 81 views
3

我只是想知道爲什麼__import__()加載一個包時調用__init__模塊兩次。__import __()調用__init__.py兩次?

test.py 
testpkg/ 
     __init__.py 

test.py

pkg = __import__("testpkg", fromlist=['']) 

__init__.py

print "Called." 

python test.py調用後。將被打印出兩次。 python爲什麼執行__init__「模塊」兩次?

+0

我無法在Python 2.6.5上重現此行爲。你正在使用哪個版本?你確定這是你在那裏發佈的完整代碼嗎? – 2010-09-19 10:05:29

+0

我正在使用Python 2.6.4。這兩行代碼就是我用來重現的一切。我剛剛嘗試了Python 2.4.3,我得到了相同的結果。 – 2010-09-19 10:16:32

+0

我使用g.c.c在linux2上的python 2.6.5上得到它4.4.3 – aaronasterling 2010-09-19 10:21:50

回答

5

這是一個Python錯誤。傳遞空字符串作爲fromlist的一個元素是非法的,應該引發異常。

有沒有必要包括""fromlist;這是隱含的 - 模塊本身始終加載。實際發生的情況是module.submodule字符串正在使用空字符串,從而導致模塊名稱testpkg.,後續句點。這是從字面上導入的,因爲它的名稱不同於testpkg,所以它作爲單獨的模塊導入。

試試這個:

pkg = __import__("testpkg", fromlist=['']) 
import sys 
print sys["testpkg"] 
print sys["testpkg."] 

...你會看到重複的模塊。

如果還沒有人的話,有人應該在此上提交一張票;現在太累了,我自己也不想做。

+0

注意:在Python 2.6.4和3.1.1中發生了這種情況。如果你提交了一個bug,請確保它尚未被更新版本修復。 – 2010-09-19 10:14:15

+0

已經有票據2090 for python 2.7,但是我沒有看到這個頁面上提到的任何版本的消息,所以我添加了一條評論。 – aaronasterling 2010-09-19 10:34:29

+0

你說得對。在用空列表替換['']後,'__init__'模塊只被調用一次。剛剛修復了SO-Answer我從這個代碼複製了。 – 2010-09-19 10:56:03

5

使用fromlist=[''] hack導入特定的模塊被python-dev明確地壓住了。雖然它已被filed as an issue修復的可能性很低,因爲這被認爲是錯誤的使用fromlist開始而不是必然的錯誤和更好的解決方案可用。

你應該做的是使用importlib.import_module(在Python 2.7和Python 3.1的標準庫中提供,或者從兼容PyPI的Python中返回到Python 2.3以及從1.1開始包含在Django中作爲django.utils.importlib)。它可以防止此問題的發生,爲導入模塊提供更好的編程接口,甚至可以在指定要導入的包時使用相對導入。

如果你真的不能使用導入庫(例如,依賴的PyPI不,即使你可以自由複製感謝PSF許可證的代碼,並允許它是很短),那麼你應該做__import__("some.module"); mod = sys.modules["some.module"]。這是官方的,python-dev認可的解決方案(但只有你不能使用importlib)。