[英]What happens when python's reload() does not find the module file?
我在运行时为我的应用程序生成代码,因此我需要重新加载一些模块,以免重新启动。
我生成的程序包可能包含新文件,也可能删除了文件(请确保每次生成代码时都会删除所有.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,但是我的模块是否已从运行时中删除?
不, 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]
- 编辑 :糟糕的Ashwini Chaudhary比我快:)
在发布此信息之前,应该做更多的研究。
我将回答我自己的问题:希望对某些人来说可能很有趣。
想象一下,我已经导入了我的模块一次:
import plop
如果删除了plop.py
和plop.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字典。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.