我有一台运行时间较长的 Python 服务器,并且希望能够在不重新启动服务器的情况下升级服务。最好的方法是什么?
if foo.py has changed:
unimport foo <-- How do I do this?
import foo
myfoo = foo.Foo()
您可以通过使用内置reload
功能来reload
已导入的模块:
from importlib import reload # Python 3.4+ only.
import foo
while True:
# Do some things.
if is_changed(foo):
foo = reload(foo)
在 Python 3 中, reload
已移至imp
模块。在 3.4 中,不推荐使用imp
而支持importlib
,并且将reload
添加到后者中。如果定位到 3 或更高版本,则在调用reload
或导入它时参考相应的模块。
我认为这就是您想要的。像 Django 开发服务器这样的 Web 服务器都使用此功能,这样您就可以看到代码更改的效果,而无需重新启动服务器进程本身。
引用文档:
重新编译 Python 模块的代码并重新执行模块级代码,从而定义了一组新对象,这些对象绑定到模块字典中的名称。扩展模块的 init 函数不会被第二次调用。与 Python 中的所有其他对象一样,旧对象仅在其引用计数降至零后才被回收。模块名称空间中的名称将更新为指向任何新的或更改的对象。对旧对象的其他引用(例如模块外部的名称)不会反弹以引用新对象,并且如果需要的话,必须在出现它们的每个命名空间中进行更新。
正如您在问题中指出的那样,如果Foo
类位于foo
模块中,则必须重新Foo
对象。
在 Python 3.0–3.3 中,您将使用: imp.reload(module)
但是, 在 3.4 中不推荐使用imp
而推荐使用importlib
(感谢@Stefan! )。
我认为 ,因此,尽管不确定,您现在将使用importlib.reload(module)
。
如果模块不是纯 Python,则删除模块可能会特别困难。
以下是一些信息: 我如何真正删除导入的模块?
您可以使用 sys.getrefcount()来查找实际的引用数。
>>> import sys, empty, os
>>> sys.getrefcount(sys)
9
>>> sys.getrefcount(os)
6
>>> sys.getrefcount(empty)
3
大于 3 的数字表示将很难摆脱该模块。自制的 “空”(不包含任何内容)模块应在回收后进行垃圾回收
>>> del sys.modules["empty"]
>>> del empty
作为第三个引用是 getrefcount()函数的构件。