我如何卸载(重新加载)模块?

问题描述 投票:746回答:18

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

if foo.py has changed:
    unimport foo  <-- How do I do this?
    import foo
    myfoo = foo.Foo()
python module reload python-import
18个回答
714
投票

您可以在使用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中,旧对象只是在引用计数后回收降为零。模块中的名称名称空间已更新为指向任何新的或更改的对象。其他对旧对象的引用(例如模块外部的名称)不是反弹以引用新对象并且必须在每个命名空间中进行更新如果需要的话,它们发生的位置。

正如您在问题中指出的,如果importlib类驻留在importlib模块中,则必须重构reload对象。


12
投票

如果您是服务器中的[[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)


7
投票
对于像我这样想要卸载所有模块的人(在math下的Python解释器中运行时:

IPython shell

更多信息位于

ipython


5
投票
思想特质具有一个可以很好地完成此任务的模块。 jupyter console

它将重新加载已更改的任何模块,并更新正在使用该模块的其他模块和实例对象。它在大多数情况下都无法使用jupyter qtconsole方法工作,并且可能会阻塞类继承,但是在编写PyQt guis或运行在诸如Maya之类的程序中的东西时,不必重新启动宿主应用程序,这为我节省了很多时间。或Nuke。可能20-30%的时间都无效,但是仍然非常有用。

Enthought的程序包不会在文件更改时立即重新加载文件-您必须明确地调用它-但是如果您真的需要它,那么实现起来应该不那么困难


5
投票
正在使用python 3并从importlib重新加载的人。

[如果您遇到问题,好像模块无法重新加载...那是因为它需要一些时间来重新编译pyc(最长60秒)。我写此提示只是想知道您是否经历过这种情况。问题。


3
投票
2018年2月1日

    模块%load_ext autoreload %autoreload 2 必须提前成功导入。
  1. [2options 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.

  • 3
    投票
    其他选项。看到Python默认Emacs只会重新导入作为参数传递的库。它

    不会重新加载您的库导入的库。如果您更改了很多文件并且要导入的包有些复杂,则必须执行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__


    1
    投票
    对我来说,Abaqus就是这种方式。假设您的文件是Class_VerticesEdges.py

    foo


    0
    投票
    另一种方法可以是在函数中导入模块。这样,当函数完成时,模块将收集垃圾。

    0
    投票
    [尝试在Sublime Text中重新加载某些东西时遇到了很多麻烦,但最终我可以编写此实用程序,基于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解释器)。

    245
    投票

    在Python 3.0–3.3中,您将使用:reload

    reloadFoo这个问题。

    但是,Foo(感谢foo)。

    思考,因此,尽管不确定,您现在将使用imp.reload(module)


    88
    投票

    如果不是纯Python的话,删除模块会特别困难。

    以下是一些信息:imp.reload(module)

    您可以使用sys.getrefcount()来找出引用。

    BDFL

    大于3的数字表示很难摆脱模块。本土的“空”(不包含任何内容)模块应该是之后收集的垃圾

    answered

    因为第三个参考是人工制品getrefcount()函数的代码。


    67
    投票

    imp was deprecated in 3.4, in favour of importlib,但前提是它是完全独立的。如果还有其他引用该模块(或属于该模块的任何对象)的引用,那么您将得到细微而奇怪的错误,这些错误是由于旧代码的停留时间超出您的预期而导致的,并且imp之类的代码无法在不同的模块上正常工作相同代码的版本。

    如果具有单向依赖关系,则还必须重新加载所有依赖于重新加载的模块的模块,以摆脱对旧代码的所有引用。然后递归地依赖于重新加载的模块重新加载模块。

    如果具有循环依赖关系(例如在处理重新加载程序包时很常见),则必须一次性卸载组中的所有模块。您无法使用importlib进行此操作,因为它会在刷新依赖关系之前重新导入每个模块,从而允许旧引用爬到新模块中。

    在这种情况下,唯一的方法是破解@Stefan!,这是不受支持的。您必须仔细检查并删除要在下次导入时重新加载的每个importlib.reload(module)条目,还必须删除其值为importlib.reload(module)的条目,以处理与缓存失败的相对导入有关的实现问题。它并不是很好,但是只要您有一套完全独立的依赖项,并且不会将引用保留在其代码库之外,它就可以使用。

    最好重新启动服务器。 : - )



    56
    投票

    对于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"]
    

    21
    投票

    以下代码允许您与Python 2/3兼容:

    reload()

    您可以在两个版本中将其用作reload(module) ,这使事情更简单。


    17
    投票

    接受的答案不处理来自X导入Y的情况。此代码也可以处理它,也可以处理标准的导入情况:

    reload from module imp

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


    15
    投票

    这是重新加载模块的现代方法:

    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) 模块。

    © www.soinside.com 2019 - 2024. All rights reserved.