2012-07-23 63 views
3

關於重新導入SO有很多問題和答案,但它似乎都非常違反直覺,不知道背後的機制。爲什麼你不能在Python中重新導入?

如果導入模塊,改變的內容,然後嘗試再次導入它,你會發現,第二進口沒有任何效果:

>>> import foo # foo.py contains: bar = 'original' 
>>> print foo.bar 
original 
>>> # edit foo.py and change to: bar = 'changed' 
>>> import foo 
>>> print foo.bar 
original 

我是一個很快樂的人,當我發現reload

>>> reload(foo) 
>>> print foo.bar 
changed 

但是還有當你正從一個模塊項目不容易解決,而不用導入模塊本身:

>>> from foo import baz 
>>> print baz 
original 
>>> # change foo.py from baz = 'original' to baz = 'changed' 
>>> from foo import baz 
>>> print baz 
original 
>>> reload(foo) 
Traceback (most recent call last): 
    File "<pyshell#10>", line 1, in <module> 
    reload(foo) 
NameError: name 'foo' is not defined 

爲什麼當您給它一個新的import語句時Python不會更新導入的項目?

+0

如果你想在你的Python系統中自動重載系統PHP,可以考慮fork-loop:http://opensourcehacker.com/2011/11/08/sauna-reload-the-most-awesomely-named- python-package-ever/ – 2012-07-23 18:59:22

+0

@MikkoOhtamaa,導致問題的用例不同,特別是從交互式會話更新和測試模塊。這個交互式會話有我不想扔掉的數據。 – 2012-07-23 19:05:01

回答

10

當您導入模塊時,它會緩存在sys.modules中。任何在同一會話中再次導入相同模塊的嘗試只會返回已存在的模塊。這加快了從多個位置導入模塊的整體體驗。它還允許模塊在所有導入之間共享其自己的對象,因爲每次都返回相同的模塊。

如前所述,您可以使用reload重新導入整個模塊。檢查文檔的警告,因爲即使這不是傻瓜證明。

當您從模塊中導入特定項目時,整個模塊將按照上述方式導入,然後您請求的對象將被放置在您的名稱空間中。 reload不起作用,因爲這些對象不是模塊,並且您從未收到對模塊本身的引用。的解決辦法是去的模塊的引用,重新加載它,然後重新導入:

>>> from foo import baz 
>>> print baz 
original 
>>> # change foo.py from baz = 'original' to baz = 'changed' 
>>> import foo 
>>> reload(foo) 
>>> from foo import baz 
>>> print baz 
changed 
2

了簡單的解釋「爲什麼」是import語句涉及到兩個操作:加載模塊(即運行其中的代碼),並將名稱導入導入模塊的名稱空間。只重新導入會重做第二個操作。原因在於第一次操作在計算和內存資源方面可能是昂貴的。

reload是作爲重做第一個操作的方式提供的,但正如您所看到的,它需要模塊名稱。然而,不要被愚弄,因爲認爲from foo import bar不是加載整個模塊。它的確如此。所有模塊的代碼都已運行,只是您只能引用您明確導入的名稱(例如,bar)。出於這個原因,導入模塊和不導入模塊幾乎沒有什麼區別。唯一的區別是命名空間問題。因此,如果您認爲您可能需要重新加載模塊foo,則應繼續並執行import foo。如果你願意,你可以做到這一點刷新導入的名稱:

import foo 
from foo import bar 
# later... 
reload(foo) 
from foo import bar 

還有另外一個原因,你不能重新導入個人的名字,這是Python有沒有改變物體提到的方式;它只能重新命名這些名稱。假如你這樣做:

from foo import bar 
newBar = bar 
from foo import bar 

即使第二進口確實刷新條的值,它可能永遠不會刷新newBar的價值,因爲既不富也不酒吧知道你創建一個額外的名稱的任何方式參考吧。避免重新命名個人名字會阻止你陷入這個陷阱;如果人們認爲重新輸入會刷新名稱,很容易忘記它仍然不會刷新對象。

相關問題