0

我在运行时为我的应用程序生成代码,因此我需要重新加载我的一些模块以免重新启动。

我生成的包可能包含新文件或删除了文件(只是为了确保每次生成代码时都会删除所有 .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,但是我的模块是否从运行时中删除了?

4

2 回答 2

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]
于 2013-05-07T07:18:27.143 回答
0

--编辑:哎呀 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 字典。

于 2013-05-07T07:36:01.983 回答