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

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

当前回答

如果一个模块不是纯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

接受的答案不处理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")

在重新加载的情况下,我们将顶级名称重新分配给新加载的模块中存储的值,从而更新这些值。

如果一个模块不是纯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()函数的。

以Abaqus为例,这就是它的工作方式。 假设你的文件是Class_VerticesEdges.py

sys.path.append('D:\...\My Pythons')
if 'Class_VerticesEdges' in sys.modules:  
    del sys.modules['Class_VerticesEdges']
    print 'old module Class_VerticesEdges deleted'
from Class_VerticesEdges import *
reload(sys.modules['Class_VerticesEdges'])

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

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)将重载数学模块。