我有一个长期运行的Python服务器,希望能够在不重新启动服务器的情况下升级服务。最好的方法是什么?
if foo.py has changed:
unimport foo <-- How do I do this?
import foo
myfoo = foo.Foo()
我有一个长期运行的Python服务器,希望能够在不重新启动服务器的情况下升级服务。最好的方法是什么?
if foo.py has changed:
unimport foo <-- How do I do this?
import foo
myfoo = foo.Foo()
当前回答
这是重新加载一个模块的现代方式:
from importlib import reload
如果你想支持3.5以上的Python版本,请使用以下命令:
from sys import version_info
if version_info[0] < 3:
pass # Python 2 has built in reload
elif version_info[0] == 3 and version_info[1] <= 4:
from imp import reload # Python 3.0 - 3.4
else:
from importlib import reload # Python 3.5+
这定义了一个重载方法,可以通过模块调用来重载它。例如,reload(math)将重载数学模块。
其他回答
在Python 3.0-3.3中,您将使用:
BDFL已经回答了这个问题。
然而,imp在3.4中被弃用了,取而代之的是importlib(谢谢@Stefan!)
因此,我认为您现在应该使用importlib.reload(module),尽管我不确定。
如果你遇到以下错误,这个答案可能会帮助你得到一个解决方案:
回溯(最近一次调用): 文件“FFFF”,第1行 NameError: name 'YYYY'没有定义
OR
回溯(最近一次调用): 文件“FFFF”,第1行 文件"/usr/local/lib/python3.7/importlib/__init__.py",第140行,重新加载 抛出TypeError("reload()参数必须是一个模块") reload()参数必须是一个模块
如果你有一个像下面这样的导入,你可能需要使用sys。模块来获取你想要重载的模块:
import importlib
import sys
from YYYY.XXX.ZZZ import CCCC
import AAA.BBB.CC
def reload(full_name)
if full_name in sys.modules:
importlib.reload(sys.modules[full_name])
reload('YYYY.XXX.ZZZ') # this is fine in both cases
reload('AAA.BBB.CC')
importlib.reload(YYYY.XXX.ZZZ) # in my case: this fails
importlib.reload(AAA.BBB.CC) # and this is ok
主要的问题是进口。重载只接受模块而不接受字符串。
重新加载(模块),但前提是它是完全独立的。如果其他任何东西引用了该模块(或属于该模块的任何对象),那么您将会得到一些微妙而奇怪的错误,这些错误是由旧代码存在的时间比您预期的要长,并且像isinstance这样的错误在相同代码的不同版本之间无法工作。
如果有单向依赖关系,还必须重新加载依赖于重新加载的模块的所有模块,以消除对旧代码的所有引用。然后递归地重新加载依赖于重新加载模块的模块。
如果你有循环依赖关系,这是非常常见的,例如当你处理重新加载一个包时,你必须一次性卸载组中的所有模块。使用reload()无法做到这一点,因为它会在刷新依赖项之前重新导入每个模块,从而允许旧的引用渗透到新模块中。
在这种情况下,唯一的方法是入侵sys。模块,这是不受支持的。你必须仔细检查并删除每个系统。您希望在下次导入时重新加载的模块项,还可以删除值为None的项,以处理缓存失败的相对导入的实现问题。这并不是很好,但只要你有一个完全自包含的依赖集,并且不会在代码库之外留下引用,它就是可行的。
最好是重新启动服务器。:-)
从sys. exe中移除模块。modules也需要删除'None'类型。
方法1:
import sys
import json ## your module
for mod in [ m for m in sys.modules if m.lstrip('_').startswith('json') or sys.modules[m] == None ]: del sys.modules[mod]
print( json.dumps( [1] ) ) ## test if functionality has been removed
方法2,使用簿记条目,删除所有依赖项:
import sys
before_import = [mod for mod in sys.modules]
import json ## your module
after_import = [mod for mod in sys.modules if mod not in before_import]
for mod in [m for m in sys.modules if m in after_import or sys.modules[m] == None]: del sys.modules[mod]
print( json.dumps( [2] ) ) ## test if functionality has been removed
可选的,只是为了确保所有的条目都出来了,如果你这样选择:
import gc
gc.collect()
对于像我这样想卸载所有模块的人(当在Emacs下的Python解释器中运行时):
for mod in sys.modules.values():
reload(mod)
更多信息请参见重新加载Python模块。