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

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

当前回答

Enthought Traits有一个模块很好地解决了这个问题。https://traits.readthedocs.org/en/4.3.0/_modules/traits/util/refresh.html

它将重新加载任何已更改的模块,并更新正在使用它的其他模块和实例对象。它在__very_private__方法的大多数时候都不起作用,并且可能会阻塞类继承,但它为我节省了大量的时间,使我不必在编写PyQt gui或在Maya或Nuke等程序中运行的东西时重新启动主机应用程序。它可能有20% - 30%的时间不起作用,但它仍然非常有帮助。

Enthought的包不会在文件更改时重新加载它们——您必须显式地调用它——但如果您确实需要它,实现它应该不是那么困难

其他回答

使用python3并从importlib重新加载的人。

如果你有问题,比如模块似乎没有重新加载…这是因为它需要一些时间重新编译pyc(最多60秒)。我写这个提示只是想让你知道你是否经历过这种问题。

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

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

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

如果你不在服务器上,但正在开发,需要频繁地重新加载一个模块,这里有一个不错的技巧。

首先,确保您使用的是Jupyter Notebook项目中的优秀IPython shell。在安装Jupyter之后,您可以使用ipython或Jupyter控制台启动它,甚至更好的是Jupyter qtconsole,这将为您提供一个在任何操作系统中都具有代码完成功能的漂亮的彩色控制台。

现在在shell中输入:

%load_ext autoreload
%autoreload 2

现在,每次运行脚本时,模块都会被重新加载。

除了2,还有其他自动重载魔法的选项:

%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.

当然,它也可以在木星笔记本上工作。

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

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

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

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

pip3 install jupyter

另一种方法是在函数中导入模块。这样,当函数完成时,模块就会被垃圾收集。