交互时在python中重新导入模块


381

我知道可以做到,但是我不记得怎么做。

如何在python中重新导入模块?场景如下:我以交互方式导入模块并对其进行修改,但随后遇到错误。我修复了.py文件中的错误,然后想重新导入固定模块而不退出python。我该怎么做 ?



Answers:


367

这应该工作:

reload(my.module)

来自Python文档

重新加载先前导入的模块。参数必须是模块对象,因此它必须已经成功导入。如果您已使用外部编辑器编辑了模块源文件,并且想在不离开Python解释器的情况下尝试新版本,则这将非常有用。

如果运行Python 3.4及更高版本,请执行import importlib,然后执行importlib.reload(nameOfModule)

不要忘记使用此方法的注意事项:

  • 重新加载模块时,将保留其字典(包含模块的全局变量)。名称的重新定义将覆盖旧的定义,因此通常这不是问题,但是如果模块的新版本未定义旧版本定义的名称,则不会删除旧定义。

  • 如果一个模块使用导入了另一个模块的对象from ... import ...,则调用reload()另一个模块的操作并未重新定义从该模块导入的对象-解决该问题的一种方法是重新执行该from语句,另一种方法是使用import和限定名称(module.*name*)。

  • 如果模块实例化一个类的实例,则重新加载定义该类的模块不会影响实例的方法定义-它们将继续使用旧的类定义。派生类也是如此。


26
如果我使用加载模块from filename import *。如何重装?
朱朱

@PeterZhu对于“从mod import fcn”情况,模块对象未添加到名称空间。因此,您需要显式导入模块,以便以后重新加载它。import foo; from foo import bar; reload(foo)
泰德

我尝试了重新加载以及自动重新加载魔术,我看到我的代码更改反映在错误消息的堆栈中,但是错误本身似乎仍然是过时的代码(例如,错误所在的行完全相同)行,如前所述,我已更改为注释,并且注释显然不会引起错误)。我的模块作为Jupyter扩展程序加载,有人知道这是否需要其他解决方法吗?谢谢!
yifanwu

1
如果按照“以名称导入mod”的形式导入函数,则需要执行以下操作:'import importlib importlib.reload(name)'
Noe

此方法可能不会覆盖其他模块对重新加载的模块的引用。有关此问题的解决方案,请参见stackoverflow.com/a/61617169/2642356
EZLearner

287

在python 3中,reload不再是内置函数。

如果您使用的是python 3.4+,则应改reloadimportlib库中使用:

import importlib
importlib.reload(some_module)

如果您使用的是Python 3.2或3.3,则应:

import imp  
imp.reload(module)  

代替。参见http://docs.python.org/3.0/library/imp.html#imp.reload

如果您使用ipython,请绝对考虑使用autoreload扩展名:

%load_ext autoreload
%autoreload 2

尽管许多Python代码是用Python 2编写的,但Python 3每天都变得越来越可行。谢谢你的提示!
亚伦·约翰逊

40
imp.reload从Python 3.4开始不推荐使用,请改用importlib.reloadfunction
jfs

1
@安德鲁谢谢!我使用了%autoreload,这很棒,我已经创建的对象无需重新创建即可自动获得类方法的更正实现
jeanmi

4
我有点晚了,但我认为,如果你需要重装的是从模块中的一个函数或类这不起作用:如果我的进口statment是from mymodule import myfunc,那么importlib.reload(myfunc)importlib.reload(mymodule.myfunc)importlib.reload(mymodule)都给出一个NameError。
帕夫

@Puff请参阅下面有关如何重新导入功能的答案
jss367,


5

如果要从模块导入特定的函数或类,可以执行以下操作:

import importlib
import sys
importlib.reload(sys.modules['my_module'])
from my_module import my_function

0

尽管提供的答案确实适用于特定模块,但它们不会重新加载子模块,如本答案所述

如果一个模块使用导入了另一个模块的对象from ... import ...,则调用reload()另一个模块的操作并未重新定义从该模块导入的对象-解决该问题的一种方法是重新执行from语句,另一种方法是使用import和限定名称(module.*name*)。

但是,如果使用__all__变量定义公共API,则可以自动重新加载所有公共可用模块:

# Python >= 3.5
import importlib
import types


def walk_reload(module: types.ModuleType) -> None:
    if hasattr(module, "__all__"):
        for submodule_name in module.__all__:
            walk_reload(getattr(module, submodule_name))
    importlib.reload(module)


walk_reload(my_module)

先前答案中指出的警告仍然有效。值得注意的是,如__all__变量所描述的那样,修改不属于公共API的子模块将不会受到使用此函数进行的重新加载的影响。同样,删除子模块的元素也不会反映在重新加载中。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.