在IPython中重新加载子模块

556 投票
14 回答
320465 浏览
提问于 2025-04-16 14:02

我现在在做一个Python项目,这个项目里有一些子模块,还用到了numpy和scipy。我在用IPython作为交互式控制台。不过,我对现在的工作流程不是很满意,希望能得到一些建议。

在IPython中,可以通过简单的import命令来加载框架。但是,有时候我需要修改框架中某个子模块的代码。这个时候,模型已经加载好了,我用IPython和它进行交互。

现在,这个框架里有很多相互依赖的模块,也就是说,当框架最开始加载的时候,主模块会导入并配置这些子模块。如果我对代码进行了修改,只有在使用reload(main_mod.sub_mod)重新加载模块时,修改才会生效。这就很麻烦,因为我需要逐个使用完整路径重新加载所有修改过的模块。如果reload(main_module)能同时重新加载所有子模块,但不重新加载numpy和scipy,那就方便多了。

14 个回答

42

在IPython 0.12版本(可能更早的版本也可以),你可以使用这个:

%load_ext autoreload
%autoreload 2

这基本上和pv给出的答案是一样的,只是这个扩展的名字换了,现在是通过%load_ext来加载的。

115

名为 importlib 的模块可以让你访问 Python 的导入内部机制。特别是,它提供了一个函数 importlib.reload()

import importlib
importlib.reload(my_module)

%autoreload 不同,importlib.reload() 还会重置模块中设置的全局变量。在大多数情况下,这正是你想要的效果。

importlib 从 Python 3.1 开始才可以使用。如果你使用的是更早的版本,就需要用到 imp 模块。

我建议你查看一下 importlib.reload() 的文档,了解这个函数的所有注意事项(比如递归重载、旧对象定义仍然存在的情况等等)。

864

IPython 有一些很方便的自动重载功能:

%load_ext autoreload
%autoreload 2

每次执行新的一行代码之前,它会自动重新加载所有有改动的模块。这种工作方式和 dreload 有点不同。使用时要注意一些问题,可以输入 %autoreload? 来查看可能出现的错误。


如果你想一直启用这个设置,可以修改你的 IPython 配置文件 ~/.ipython/profile_default/ipython_config.py[1],并添加以下内容:

c.InteractiveShellApp.extensions = ['autoreload']     
c.InteractiveShellApp.exec_lines = ['%autoreload 2']

感谢 @Kos 在下面的评论中提供的信息。

[1] 如果你没有 ~/.ipython/profile_default/ipython_config.py 这个文件,你需要先运行 ipython profile create 来创建它。或者这个文件可能在 $IPYTHONDIR 目录下。

撰写回答