2013-05-07 49 views
0

我在運行時爲我的應用程序生成代碼,因此我需要重新加載一些模塊以免重新啓動。當python的reload()沒有找到模塊文件時會發生什麼?

我生成的軟件包可能包含新文件或刪除了文件(只是爲了確保每次生成代碼時刪除所有.pyc文件)。

我做這樣的事情:

for name, module in sys.modules.iteritems(): 
    if name.startswith('my.dynamic.package.') and module is not None: 
    try:  
     reload(module) 
    except ImportError: 
     pass 

所以,如果我的一些模塊被刪除呢?我會像預期的那樣得到ImportError,但是我的模塊是從運行時刪除的?

回答

1

不,reload永不刪除模塊對象。它只是簡單地修改模塊對象。所以,如果重新加載失敗,舊的綁定仍然保持不變。

http://docs.python.org/2/library/functions.html#reload

#so.py 
i = 0 
lis = [1,2,3] 
dic = {"a":1, "b":2} 

現在讓我們導入這個模塊:

>>> import so 
>>> x = so.lis[0] 
>>> so.lis[0]=0   #modify so.lis 
>>> so.dic["a"] = so.lis #modify so.dic 
>>> !rm -r so.py so.pyc #delete both so.py and so.pyc 
>>> try:     #try reloading 
...  reload(so) 
... except ImportError: 
...  pass 
... 
>>> so.lis     #previous binding are still intact 
[0, 2, 3] 
>>> x 
1 
>>> so.dic 
{'a': [0, 2, 3], 'b': 2} 

現在不是刪除,我們會嘗試修改模塊:

#so.py 
i = 0 
lis = [1,2,3,4] 
dic = {"a":1, "b":2} 

現在導入:

>>> import so 
>>> lis = so.lis  #add a new reference to it 
>>> so.lis[0] = 0 #modify so.lis 
>>> so.i 
0 

現在修改so.py到:

#so.py 
i = 0 
lis = [1,2,3]  #updated lis 
dic = {"a":1, "b":2} 

現在reload()

>>> reload(so) 
<module 'so' from 'so.py'> 

>>> so.lis  #got updated 
[1, 2, 3] 
>>> lis   #old so.lis object is still in memory as it's reference count is not 0 
[0, 2, 3, 4] 
0

- 編輯:哎呦阿什維尼·喬杜裏比我:)

應該有更快在發佈之前做了更多的研究。

我會回答我自己的問題:希望這對你們中的一些人來說可能很有趣。

想象我已經導入我的模塊一次:

import plop 

如果plop.pyplop.pyc被刪除:

>>> reload(plop) 
ImportError: no module named plop 

但要小心!該模塊不會從模塊字典中刪除。

>>> print repr(sys.modules['plop']) 
<module 'plop' from plop.py> 

不過,我可以將其刪除手動

>>> del sys.modules['plop'] 
>>> import plop 
ImportError: no module named plop 

在這種情況下,導入錯誤的:無論我就已經導入模塊,代碼仍然是必然選擇在本地變量名導入時間 - 通常是模塊名稱。該模塊仍然存在於我的運行時。

所以我只做了一點實驗。

如果某個地方在我的代碼我碰巧有進口功能從我的模塊,無論是重裝作品與否,我還是會有老功能參考。

>>> from plop import somefunc 
>>> somefunc() 
i am the first version! 
>>> # code is regenerated 
>>> reload(plop) 
>>> # should print "i am the second version!" 
>>> somefunc() 
i am the first version! 

如果我用了plop.somefunc()相反,我會一直跟上時代的,當箱子重裝工程。

我的結論是:當我重新加載模塊時,無論我需要使用什麼模塊或模塊字段,我都應該小心並且重新導入。如果無法重新加載,我應該清理sys.modules字典。