我有一个长期运行的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

其他回答

其他选项。请参阅Python默认importlib。Reload将只是重新导入作为参数传递的库。它不会重新加载库导入的库。如果您更改了很多文件,并且有一个有点复杂的包要导入,那么您必须进行深度重载。

如果你安装了IPython或Jupyter,你可以使用一个函数来深度重载所有库:

from IPython.lib.deepreload import reload as dreload
dreload(foo)

如果你没有Jupyter,在你的shell中使用以下命令安装它:

pip3 install jupyter

如果你遇到以下错误,这个答案可能会帮助你得到一个解决方案:

回溯(最近一次调用): 文件“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

主要的问题是进口。重载只接受模块而不接受字符串。

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

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

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

以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'])

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

BDFL已经回答了这个问题。

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

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