我有一个长期运行的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()
当前回答
在Python 3.0-3.3中,您将使用:
BDFL已经回答了这个问题。
然而,imp在3.4中被弃用了,取而代之的是importlib(谢谢@Stefan!)
因此,我认为您现在应该使用importlib.reload(module),尽管我不确定。
其他回答
如果你不在服务器上,但正在开发,需要频繁地重新加载一个模块,这里有一个不错的技巧。
首先,确保您使用的是Jupyter Notebook项目中的优秀IPython shell。在安装Jupyter之后,您可以使用ipython或Jupyter控制台启动它,甚至更好的是Jupyter qtconsole,这将为您提供一个在任何操作系统中都具有代码完成功能的漂亮的彩色控制台。
现在在shell中输入:
%load_ext autoreload
%autoreload 2
现在,每次运行脚本时,模块都会被重新加载。
除了2,还有其他自动重载魔法的选项:
%autoreload
Reload all modules (except those excluded by %aimport) automatically now.
%autoreload 0
Disable automatic reloading.
%autoreload 1
Reload all modules imported with %aimport every time before executing the Python code typed.
%autoreload 2
Reload all modules (except those excluded by %aimport) every time before
executing the Python code typed.
当然,它也可以在木星笔记本上工作。
我遇到了很多麻烦,试图在Sublime Text中重新加载一些东西,但最后我可以编写这个实用程序来基于sublime_plugin.py用于重新加载模块的代码在Sublime Text上重新加载模块。
下面的代码允许您从名称上带有空格的路径重新加载模块,然后在重新加载后,您可以像往常一样导入。
def reload_module(full_module_name):
"""
Assuming the folder `full_module_name` is a folder inside some
folder on the python sys.path, for example, sys.path as `C:/`, and
you are inside the folder `C:/Path With Spaces` on the file
`C:/Path With Spaces/main.py` and want to re-import some files on
the folder `C:/Path With Spaces/tests`
@param full_module_name the relative full path to the module file
you want to reload from a folder on the
python `sys.path`
"""
import imp
import sys
import importlib
if full_module_name in sys.modules:
module_object = sys.modules[full_module_name]
module_object = imp.reload( module_object )
else:
importlib.import_module( full_module_name )
def run_tests():
print( "\n\n" )
reload_module( "Path With Spaces.tests.semantic_linefeed_unit_tests" )
reload_module( "Path With Spaces.tests.semantic_linefeed_manual_tests" )
from .tests import semantic_linefeed_unit_tests
from .tests import semantic_linefeed_manual_tests
semantic_linefeed_unit_tests.run_unit_tests()
semantic_linefeed_manual_tests.run_manual_tests()
if __name__ == "__main__":
run_tests()
如果您第一次运行,这将加载模块,但如果稍后您可以再次运行run_tests()方法/函数,它将重新加载测试文件。对于Sublime Text (Python 3.3.6),这种情况经常发生,因为它的解释器从不关闭(除非你重新启动Sublime Text,即Python3.3解释器)。
如果一个模块不是纯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()函数的。
Python不会在重载时重新计算子模块地址,如果它在sys.modules中
这里有一个变通办法,虽然不完美,但有效。
# Created by BaiJiFeiLong@gmail.com at 2022/2/19 18:50
import importlib
import types
import urllib.parse
import urllib.request
def reloadModuleWithChildren(mod):
mod = importlib.reload(mod)
for k, v in mod.__dict__.items():
if isinstance(v, types.ModuleType):
setattr(mod, k, importlib.import_module(v.__name__))
fakeParse = types.ModuleType("urllib.parse")
realParse = urllib.parse
urllib.parse = fakeParse
assert urllib.parse is fakeParse
importlib.reload(urllib)
assert urllib.parse is fakeParse
assert getattr(urllib, "parse") is fakeParse
reloadModuleWithChildren(urllib)
assert urllib.parse is not fakeParse
assert urllib.parse is realParse
如果你遇到以下错误,这个答案可能会帮助你得到一个解决方案:
回溯(最近一次调用): 文件“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
主要的问题是进口。重载只接受模块而不接受字符串。