在IPython中重新加载子模块


363

目前,我正在处理一个包含子模块并使用numpy / scipy的python项目。Ipython用作交互式控制台。不幸的是,我对现在使用的工作流程不是很满意,请多多指教。

在IPython中,该框架是通过一个简单的import命令加载的。但是,通常有必要在框架的子模块之一中更改代码。至此,已经加载了一个模型,并且我使用IPython与之交互。

现在,该框架包含许多相互依赖的模块,即,在最初加载该框架时,主模块正在导入和配置子模块。仅当使用重新加载模块时,才执行对代码的更改reload(main_mod.sub_mod)。这很麻烦,因为我需要使用完整路径分别重新加载所有更改的模块。如果reload(main_module)还重新加载所有子模块,但又不重新加载numpy / scipy ,将非常方便。


您是否愿意详细说明However, it is often necessary to change code in one of the submodules of the framework.为什么呢necessary to change code?谢谢

16
@eat:该框架正在不断开发中,因此代码库不断变化。
阿兰(Alain)

Answers:


531

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


63
我有c.InteractiveShellApp.extensions = ['autoreload']c.InteractiveShellApp.exec_lines = ['%autoreload 2']在我的~/.ipython/profile_default/ipython_config.py
科斯(Kos)

4
但是,这可能会降低性能,因此请谨慎使用。
asmeurer 2013年

3
仅当您在Ipython shell中按Enter键时才执行重新加载,并且通常不会引起注意。
光伏。

3
在调试软件包时,这可以很好地工作,因此dreload的目的是什么,似乎dreload太具有侵入性,并且在加载某些软件包(如matplotlib)时显示错误。
dashesy 2013年

3
如果使用@Kos方法,请确保定义了c:c = get_config()
Tickon

27

在IPython 0.12(可能更早)中,您可以使用以下命令:

%load_ext autoreload
%autoreload 2

这与pv的答案基本相同,除了扩展名已重命名并现在使用加载%load_ext


20

由于某种原因,当您将代码从一个笔记本导入另一个笔记本时,这两种方法都不起作用%autoreload,也dreload似乎不起作用。只有普通的Python 可以工作:reload

reload(module)

基于[1]


10
在Python 3.4+中,您可以在importlib模块中找到重新加载。看到这个问题
Praveen

1
与该%autoreload技术不同,此方法在添加实例方法时有效。有一个开放的错误报告,为此添加了支持%autoreload
ijoseph

18

IPython提供dreload()了递归方式重新加载所有子模块。就个人而言,我更喜欢使用%run()magic命令(尽管它不会执行深度重新加载,正如John Salvatier在评论中指出的那样)。


11
我认为(不幸的是)%run script.py仅重新加载您正在调用的脚本,而不重新加载它导入的包。如果您要调试正在构建的软件包,则可能会很痛苦。
John Salvatier

2
注意 dreload在最近的IPython(例如IPython 6.0)中已由deepreload替换
丹·麦金莱

8

名为importliballow的模块可以访问导入内部构件。特别是,它提供功能importlib.reload()

import importlib
importlib.reload(my_module)

与此相反%autoreloadimportlib.reload()还重置模块中设置的全局变量。在大多数情况下,这就是您想要的。

importlib仅从Python 3.1开始可用。对于旧版本,您必须使用module imp


唯一对我
有用的

5

http://shawnleezx.github.io/blog/2015/08/03/some-notes-on-ipython-startup-script/

为了避免一遍又一遍地输入这些魔术函数,可以将它们放在ipython启动脚本中(用.ipython / profile_default / startup下的.py后缀命名。该文件夹下的所有python脚本将按照词法顺序加载),看起来如下:

from IPython import get_ipython
ipython = get_ipython()

ipython.magic("pylab")
ipython.magic("load_ext autoreload")
ipython.magic("autoreload 2")

如果您正在使用%run script.pyIPython REPL中的脚本运行脚本,这似乎也行得通
Patrick Sanan

3

这个怎么样:

import inspect

# needs to be primed with an empty set for loaded
def recursively_reload_all_submodules(module, loaded=None):
    for name in dir(module):
        member = getattr(module, name)
        if inspect.ismodule(member) and member not in loaded:
            recursively_reload_all_submodules(member, loaded)
    loaded.add(module)
    reload(module)

import mymodule
recursively_reload_all_submodules(mymodule, set())

这样可以有效地重新加载您为其提供的整个模块树和子模块树。您也可以将此函数放在.ipythonrc中(我认为),以便每次启动解释器时都将其加载。


看起来不错,但是可能是因为它没有涵盖使用from ... import ...或导入的模块或模块成员import ... as。至少在终端上进行交互工作时,这常常给我带来一些麻烦。我继续在IPython中使用存储的宏,这些宏执行必要的导入和设置以开始在预定义状态下工作。
Bernhard

它实际上做封面from ... import ...,并import ... as只要你输入的东西是一个模块。它唯一无法覆盖的是未从__init__.py文件加载的包中的模块。对于包,您可能可以检查模块的__path__属性是否为目录。如果是,请遍历它并递归导入所有可以找到的模块。我之所以没有写这部分,是因为作者没有要求软件包的解决方案。
YH Wong

确实,这看起来不错。我考虑了这种可能性,同时我期望会有一些内置功能,即基于this。但是,我不清楚如何使用它。在发布原始问题之前应该进行一些挖掘之后,我找到了这个扩展名
Alain

您也可以使用它pkgutil来获取包中的所有子模块,即使该包未将子模块导入顶部模块中也是如此。stackoverflow.com/a/1707786/1243926
osa

您还必须执行以下操作:对于sys.modules:
in aoeu256's

2

另外一个选项:

$ cat << EOF > ~/.ipython/profile_default/startup/50-autoreload.ipy
%load_ext autoreload
%autoreload 2
EOF

在Ubuntu 14.04上的ipython和ipython3 v5.1.0上进行了验证。


1

我的重载标准做法是在首次打开时将两种方法结合起来IPython

from IPython.lib.deepreload import reload
%load_ext autoreload
%autoreload 2

在执行此操作之前加载模块将导致即使使用手册也无法重新加载它们reload(module_name)。我仍然很少遇到类方法无法重装的莫名其妙的问题,而我尚未研究过。


1

请注意,autoreload如果您手动保存更改的文件(例如,使用ctrl + s或cmd + s),则上述内容仅在IntelliJ中有效。自动保存似乎不起作用。


我确认PyCharm也是如此。
tsando

0

在Anaconda的Jupyter笔记本上,执行以下操作:

%load_ext autoreload
%autoreload 2

产生了消息:

autoreload扩展程序已加载。要重新加载它,请使用: %reload_ext autoreload

看起来最好这样做:

%reload_ext autoreload
%autoreload 2

版本信息:

笔记本服务器的版本为5.0.0,并且运行在:Python 3.6.2 | Anaconda,Inc. | (默认值,2017年9月20日,13:35:58)[MSC v.1900 32位(Intel)]


0

此操作将不会重新加载任何子对象,我相信您必须为此使用IPython的deepreload。

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.