我有一个长期运行的Python服务器,希望能够在不重新启动服务器的情况下升级服务。最好的方法是什么?

if foo.py has changed:
    unimport foo  <-- How do I do this?
    import foo
    myfoo = foo.Foo()

当前回答

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

其他回答

if 'myModule' in sys.modules:  
    del sys.modules["myModule"]

这是重新加载一个模块的现代方式:

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不会在重载时重新计算子模块地址,如果它在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

对于像我这样想卸载所有模块的人(当在Emacs下的Python解释器中运行时):

   for mod in sys.modules.values():
      reload(mod)

更多信息请参见重新加载Python模块。

在Python 3.0-3.3中,您将使用:

BDFL已经回答了这个问题。

然而,imp在3.4中被弃用了,取而代之的是importlib(谢谢@Stefan!)

因此,我认为您现在应该使用importlib.reload(module),尽管我不确定。