繁体   English   中英

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

[英]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.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字典。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM