我有一个长期运行的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()
当前回答
从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模块。
接受的答案不处理from X import Y的情况。这段代码处理了它和标准的导入情况:
def importOrReload(module_name, *names):
import sys
if module_name in sys.modules:
reload(sys.modules[module_name])
else:
__import__(module_name, fromlist=names)
for name in names:
globals()[name] = getattr(sys.modules[module_name], name)
# use instead of: from dfly_parser import parseMessages
importOrReload("dfly_parser", "parseMessages")
在重新加载的情况下,我们将顶级名称重新分配给新加载的模块中存储的值,从而更新这些值。
这是重新加载一个模块的现代方式:
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)将重载数学模块。
我遇到了很多麻烦,试图在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解释器)。
Enthought Traits有一个模块很好地解决了这个问题。https://traits.readthedocs.org/en/4.3.0/_modules/traits/util/refresh.html
它将重新加载任何已更改的模块,并更新正在使用它的其他模块和实例对象。它在__very_private__方法的大多数时候都不起作用,并且可能会阻塞类继承,但它为我节省了大量的时间,使我不必在编写PyQt gui或在Maya或Nuke等程序中运行的东西时重新启动主机应用程序。它可能有20% - 30%的时间不起作用,但它仍然非常有帮助。
Enthought的包不会在文件更改时重新加载它们——您必须显式地调用它——但如果您确实需要它,实现它应该不是那么困难