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

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

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

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

I know it can be done, but I never remember how.

How can you reimport a module in python? The scenario is as follows: I import a module interactively and tinker with it, but then I face an error. I fix the error in the .py file and then I want to reimport the fixed module without quitting python. How can I do it ?


回答 0

这应该工作:

reload(my.module)

来自Python文档

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

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

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

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

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

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

This should work:

reload(my.module)

From the Python docs

Reload a previously imported module. The argument must be a module object, so it must have been successfully imported before. This is useful if you have edited the module source file using an external editor and want to try out the new version without leaving the Python interpreter.

If running Python 3.4 and up, do import importlib, then do importlib.reload(nameOfModule).

Don’t forget the caveats of using this method:

  • When a module is reloaded, its dictionary (containing the module’s global variables) is retained. Redefinitions of names will override the old definitions, so this is generally not a problem, but if the new version of a module does not define a name that was defined by the old version, the old definition is not removed.

  • If a module imports objects from another module using from ... import ..., calling reload() for the other module does not redefine the objects imported from it — one way around this is to re-execute the from statement, another is to use import and qualified names (module.*name*) instead.

  • If a module instantiates instances of a class, reloading the module that defines the class does not affect the method definitions of the instances — they continue to use the old class definition. The same is true for derived classes.


回答 1

在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

In python 3, reload is no longer a built in function.

If you are using python 3.4+ you should use reload from the importlib library instead:

import importlib
importlib.reload(some_module)

If you are using python 3.2 or 3.3 you should:

import imp  
imp.reload(module)  

instead. See http://docs.python.org/3.0/library/imp.html#imp.reload

If you are using ipython, definitely consider using the autoreload extension:

%load_ext autoreload
%autoreload 2

回答 2

实际上,在Python 3中,该模块imp被标记为DEPRECATED。好吧,至少对于3.4是正确的。

而是应使用模块中的reload功能importlib

https://docs.python.org/3/library/importlib.html#importlib.reload

但是请注意,该库在最后两个次要版本中进行了一些API更改。

Actually, in Python 3 the module imp is marked as DEPRECATED. Well, at least that’s true for 3.4.

Instead the reload function from the importlib module should be used:

https://docs.python.org/3/library/importlib.html#importlib.reload

But be aware that this library had some API-changes with the last two minor versions.


回答 3

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

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

If you want to import a specific function or class from a module, you can do this:

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

回答 4

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

如果一个模块使用导入了另一个模块的对象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的子模块将不会受到使用此函数进行的重新加载的影响。同样,删除子模块的元素也不会反映在重新加载中。

Although the provided answers do work for a specific module, they won’t reload submodules, as noted in This answer:

If a module imports objects from another module using from ... import ..., calling reload() for the other module does not redefine the objects imported from it — one way around this is to re-execute the from statement, another is to use import and qualified names (module.*name*) instead.

However, if using the __all__ variable to define the public API, it is possible to automatically reload all publicly available modules:

# 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)

The caveats noted in the previous answer are still valid though. Notably, modifying a submodule that is not part of the public API as described by the __all__ variable won’t be affected by a reload using this function. Similarly, removing an element of a submodule won’t be reflected by a reload.