当python的reload()找不到模块文件时会发生什么?

时间:2013-05-07 07:15:25

标签: 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,但是我的模块是从运行时删除的吗?

2 个答案:

答案 0 :(得分: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]

答案 1 :(得分:0)

- 编辑:哎呦Ashwini Chaudhary比我更快:)

在发布之前应该做一些研究。

我将回答我自己的问题:希望你们中的一些人可能会感兴趣。

想象一下,我已经导入了我的模块一次:

import plop

如果删除了plop.pyplop.pyc

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

但要注意!该模块不会从模块dict中删除。

>>> 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 dict。