在 IPython 中重新加载子模块
- 2025-01-13 08:52:00
- admin 原创
- 25
问题描述:
目前我正在开发一个包含子模块并使用 numpy/scipy 的 Python 项目。Ipython 用作交互式控制台。不幸的是,我对目前使用的工作流程不太满意,希望得到一些建议。
在 IPython 中,框架通过一个简单的import
命令加载。但是,经常需要更改框架子模块之一中的代码。此时模型已经加载,我使用 IPython 与其交互。
现在,框架包含许多相互依赖的模块,即,当框架最初加载时,主模块正在导入和配置子模块。仅当使用重新加载模块时,才会执行对代码的更改。这很麻烦,因为我需要使用完整路径单独重新加载所有更改的模块。如果还重新加载所有子模块,但无需重新加载numpy / scipy,reload(main_mod.sub_mod)
那将非常方便。reload(main_module)
解决方案 1:
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
。
解决方案 2:
模块名称importlib
允许访问导入内部内容。特别是,它提供以下功能importlib.reload()
:
import importlib
importlib.reload(my_module)
与此相反%autoreload
,importlib.reload()
还重置模块中设置的全局变量。在大多数情况下,这就是你想要的。
importlib
仅在 Python 3.1 以上版本可用。对于旧版本,您必须使用 module imp
。
我建议阅读文档以importlib.reload()
获取此功能的所有注意事项的列表(递归重新加载,旧对象定义仍然存在的情况等......)。
解决方案 3:
在 IPython 0.12(可能更早版本)中,你可以使用以下命令:
%load_ext autoreload
%autoreload 2
这与pv.的答案基本相同,只是扩展已被重命名并且现在使用 加载%load_ext
。
解决方案 4:
出于某种原因,当你将代码从一个笔记本导入另一个笔记本%autoreload
时, 和dreload
似乎都不起作用。只有纯 Python才有效:reload
reload(module)
基于[1]。
解决方案 5:
IPython 提供dreload()
递归重新加载所有子模块的功能。就我个人而言,我更喜欢使用%run()
magic 命令(尽管它不会执行深度重新加载,正如 John Salvatier 在评论中指出的那样)。
解决方案 6:
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")
解决方案 7:
这个怎么样:
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 中(我认为),这样每次启动解释器时都会加载它。
解决方案 8:
我重新加载的标准做法是在第一次打开后结合两种方法IPython
:
from IPython.lib.deepreload import reload
%load_ext autoreload
%autoreload 2
在执行此操作之前加载模块将导致它们无法重新加载,即使使用手册也是如此reload(module_name)
。我仍然很少遇到类方法无法重新加载的莫名其妙的问题,我还没有研究过。
解决方案 9:
另一种选择:
$ cat << EOF > ~/.ipython/profile_default/startup/50-autoreload.ipy
%load_ext autoreload
%autoreload 2
EOF
在 Ubuntu 14.04 上的 ipython 和 ipython3 v5.1.0 上进行了验证。
解决方案 10:
在模块导入之前包含以下几行,首先测试自动重新加载扩展是否已经加载:
if 'autoreload' not in get_ipython().extension_manager.loaded:
%load_ext autoreload
%autoreload 2
import sys
.
.
.
解决方案 11:
我不想在长线程中添加另一个答案,但是我找到了一个可以递归重新加载子模块的解决方案,%run()
其他人可能会觉得有用(无论如何我有)
del
您希望在sys.modules
iPython 中运行时重新加载的子模块:
In[1]: from sys import modules
In[2]: del modules["mymodule.mysubmodule"] # tab completion can be used like mymodule.<tab>!
现在你的脚本将递归地重新加载这个子模块:
In[3]: %run myscript.py
解决方案 12:
请注意,上述autoreload
操作仅在您手动保存更改的文件(例如使用 ctrl+s 或 cmd+s)时才在 IntelliJ 中有效。它似乎不适用于自动保存。
解决方案 13:
在 Anaconda 上的 Jupyter Notebooks 上执行以下操作:
%load_ext autoreload
%autoreload 2
产生了以下消息:
自动重新加载扩展已加载。要重新加载,请使用:
%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)]
解决方案 14:
任何子对象都不会因此重新加载,我相信您必须使用 IPython 的 deepreload 来实现这一点。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 项目管理必备:盘点2024年13款好用的项目管理软件
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)