我有一个运行时间较长的Python服务器,希望能够在不重新启动服务器的情况下升级服务。最好的方法是什么?
if foo.py has changed:
unimport foo <-- How do I do this?
import foo
myfoo = foo.Foo()
您可以在使用reload
内置函数导入模块后重新加载它:
reload
在Python 3中,from importlib import reload # Python 3.4+ only.
import foo
while True:
# Do some things.
if is_changed(foo):
foo = reload(foo)
已移至reload
模块。在3.4中,不推荐使用imp
,而推荐使用imp
。如果定位到3或更高版本,请在调用imp
时引用相应的模块或将其导入。
我认为这就是您想要的。像Django开发服务器这样的Web服务器都使用此服务器,这样您就可以看到代码更改的效果,而无需重新启动服务器进程本身。
要引用文档:
Python模块的代码已重新编译,重新执行模块级代码,定义一组新的对象绑定到模块名称中字典。的init函数扩展模块不称为第二次。与所有其他对象一样在Python中,旧对象只是在引用计数后回收降为零。模块中的名称名称空间已更新为指向任何新的或更改的对象。其他对旧对象的引用(例如模块外部的名称)不是反弹以引用新对象并且必须在每个命名空间中进行更新如果需要的话,它们发生的位置。
如果您是服务器中的[[not,但开发中并且需要经常重新加载模块,这是一个不错的提示。
首先,请确保您使用的是Jupyter Notebook项目中出色的try:
reload
except NameError:
# Python 3
from imp import reload
。安装Jupyter之后,您可以使用reload()
或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
来启动它,它将为您提供一个漂亮的彩色控制台,可以在任何OS中完成代码。现在在您的外壳中,键入:
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(MODULE)
以外,还有其他MODULE
:
reload(math)
jupyter console
它将重新加载已更改的任何模块,并更新正在使用该模块的其他模块和实例对象。它在大多数情况下都无法使用jupyter qtconsole
方法工作,并且可能会阻塞类继承,但是在编写PyQt guis或运行在诸如Maya之类的程序中的东西时,不必重新启动宿主应用程序,这为我节省了很多时间。或Nuke。可能20-30%的时间都无效,但是仍然非常有用。
Enthought的程序包不会在文件更改时立即重新加载文件-您必须明确地调用它-但是如果您真的需要它,那么实现起来应该不那么困难
[如果您遇到问题,好像模块无法重新加载...那是因为它需要一些时间来重新编译pyc(最长60秒)。我写此提示只是想知道您是否经历过这种情况。问题。
%load_ext autoreload
%autoreload 2
必须提前成功导入。 2
,options of the autoreload magic%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.
不会重新加载您的库导入的库。如果您更改了很多文件并且要导入的包有些复杂,则必须执行deep reload。
如果安装了 for mod in sys.modules.values():
reload(mod)
或Reloading Python modules,则可以使用函数来深度重新加载所有库:https://traits.readthedocs.org/en/4.3.0/_modules/traits/util/refresh.html
如果没有Jupyter,请在外壳程序中使用以下命令将其安装:
__very_private__
foo
from importlib import reload
用于重新加载模块的代码在Sublime Text上重新加载模块。下面的代码允许您从路径上带有空格的模块中重新加载模块,然后稍后在重新加载后,您就可以像平常一样导入。
reload(foo)
如果是第一次运行,则应该加载模块,但是如果以后可以再次使用方法/功能31.5. importlib — The implementation of import — Python 3.6.4 documentation,它将重新加载测试文件。对于Sublime Text(importlib.reload
),这种情况经常发生,因为其解释器永远不会关闭(除非您重新启动Sublime Text,即IPython解释器)。
imp
was deprecated in 3.4, in favour of importlib
,但前提是它是完全独立的。如果还有其他引用该模块(或属于该模块的任何对象)的引用,那么您将得到细微而奇怪的错误,这些错误是由于旧代码的停留时间超出您的预期而导致的,并且imp
之类的代码无法在不同的模块上正常工作相同代码的版本。
如果具有单向依赖关系,则还必须重新加载所有依赖于重新加载的模块的模块,以摆脱对旧代码的所有引用。然后递归地依赖于重新加载的模块重新加载模块。
如果具有循环依赖关系(例如在处理重新加载程序包时很常见),则必须一次性卸载组中的所有模块。您无法使用importlib
进行此操作,因为它会在刷新依赖关系之前重新导入每个模块,从而允许旧引用爬到新模块中。
在这种情况下,唯一的方法是破解@Stefan!,这是不受支持的。您必须仔细检查并删除要在下次导入时重新加载的每个importlib.reload(module)
条目,还必须删除其值为importlib.reload(module)
的条目,以处理与缓存失败的相对导入有关的实现问题。它并不是很好,但是只要您有一套完全独立的依赖项,并且不会将引用保留在其代码库之外,它就可以使用。
最好重新启动服务器。 : - )
对于Python 2,使用内置函数>>> import sys, empty, os
>>> sys.getrefcount(sys)
9
>>> sys.getrefcount(os)
6
>>> sys.getrefcount(empty)
3
:
>>> del sys.modules["empty"]
>>> del empty
对于Python 2和3.2–3.3,使用reload(module)
:
isinstance
但是从版本3.4 reload()
开始是sys.modules
sys.modules
,所以请使用:
None
或
if 'myModule' in sys.modules:
del sys.modules["myModule"]
接受的答案不处理来自X导入Y的情况。此代码也可以处理它,也可以处理标准的导入情况:
reload from module imp
在重载的情况下,我们将顶级名称重新分配给新重载的模块中存储的值,从而更新它们。
这是重新加载模块的现代方法:
import imp
imp.reload(module)
如果要支持3.4之前的Python版本,请尝试以下操作:
imp
要使用它,请运行is deprecated,并用要重新加载的模块替换in favor of importlib。
例如,import importlib
importlib.reload(module)
将重新加载from importlib import reload
reload(module)
模块。