【发布时间】:2010-11-18 06:28:15
【问题描述】:
我知道可以做到,但我不记得怎么做。
如何在 python 中重新导入模块? 场景如下:我以交互方式导入一个模块并对其进行修改,但随后我遇到了错误。我修复了 .py 文件中的错误,然后我想在不退出 python 的情况下重新导入修复的模块。我该怎么做?
【问题讨论】:
标签: python
我知道可以做到,但我不记得怎么做。
如何在 python 中重新导入模块? 场景如下:我以交互方式导入一个模块并对其进行修改,但随后我遇到了错误。我修复了 .py 文件中的错误,然后我想在不退出 python 的情况下重新导入修复的模块。我该怎么做?
【问题讨论】:
标签: python
对于Python 3.4+:
import importlib
importlib.reload(nameOfModule)
对于 Python :
reload(my.module)
重新加载以前导入的模块。参数必须是模块对象,所以它必须之前已经成功导入。如果您已使用外部编辑器编辑了模块源文件并想在不离开 Python 解释器的情况下试用新版本,这将非常有用。
不要忘记使用此方法的注意事项:
当一个模块被重新加载时,它的字典(包含模块的全局变量)被保留。重新定义名称会覆盖旧定义,因此这通常不是问题,但如果模块的新版本没有定义旧版本定义的名称,则不会删除旧定义。
如果一个模块使用from ... import ...从另一个模块导入对象,则为另一个模块调用reload()不会重新定义从它导入的对象——解决这个问题的一种方法是重新执行from语句,另一种是改为使用 import 和限定名称 (module.*name*)。
如果一个模块实例化了一个类的实例,重新加载定义该类的模块不会影响实例的方法定义——它们会继续使用旧的类定义。派生类也是如此。
【讨论】:
from filename import * 加载我的模块。如何重新加载?
import foo; from foo import bar; reload(foo)
在 python 3 中,reload 不再是内置函数。
如果您使用的是 python 3.4+,则应使用 reload 库中的 reload 代替:
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
【讨论】:
from mymodule import myfunc,那么@987654336 @、importlib.reload(mymodule.myfunc)、importlib.reload(mymodule) 都给出了 NameError。
实际上,在 Python 3 中,模块 imp 被标记为已弃用。好吧,至少 3.4 是这样。
应该使用来自importlib 模块的reload 函数:
https://docs.python.org/3/library/importlib.html#importlib.reload
但请注意,该库在最后两个次要版本中有一些 API 更改。
【讨论】:
如果你想从一个模块中导入一个特定的函数或类,你可以这样做:
import importlib
import sys
importlib.reload(sys.modules['my_module'])
from my_module import my_function
【讨论】:
另一个小点:如果您使用了import some_module as sm 语法,那么您必须使用其别名(在本例中为sm)重新加载模块:
>>> import some_module as sm
...
>>> import importlib
>>> importlib.reload(some_module) # raises "NameError: name 'some_module' is not defined"
>>> importlib.reload(sm) # works
【讨论】:
import <module> as <name> 语句只是将<name> 分配给模块object。然后reload() 函数接受这个对象。 reload() 函数不关心(或知道)名称。
尽管提供的答案确实适用于特定模块,但它们不会重新加载子模块,如 This answer 中所述:
如果一个模块使用
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 的子模块不会受到使用此函数重新加载的影响。同样,删除子模块的元素不会被重新加载反映。
【讨论】:
import sys
del sys.modules['module_name']
import module_name
【讨论】: