目前我正在开发一个包含子模块并使用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? 谢谢
-
@eat:框架不断开发,因此代码库不断变化。
IPython带有一些自动重装魔法:
1 2
| %load_ext autoreload
%autoreload 2 |
它会在执行新行之前每次重新加载所有已更改的模块。它的工作方式与dreload略有不同。一些警告适用,键入%autoreload?以查看可能出错的地方。
如果要始终启用此设置,请修改IPython配置文件~/.ipython/profile_default/ipython_config.py [1]并附加:
1 2
| c.InteractiveShellApp.extensions = ['autoreload']
c.InteractiveShellApp.exec_lines = ['%autoreload 2'] |
通过以下评论获得@Kos。
[1]
如果您没有~/.ipython/profile_default/ipython_config.py文件,则需要先调用ipython profile create。或者文件可能位于$IPYTHONDIR。
-
你如何永久地做出这些改变?
-
我的~/.ipython/profile_default/ipython_config.py中有c.InteractiveShellApp.extensions = ['autoreload']和c.InteractiveShellApp.exec_lines = ['%autoreload 2']。
-
但这可能会影响性能,因此请谨慎使用。
-
只有在Ipython shell中按Enter键才会执行重新加载,而且通常不会引人注意。
-
它不适用于from ... import *类型的导入,对吧?有什么方法可以解决这个问题吗?
-
@Thorn:它在某种程度上也适用于那些,但不跟踪模块依赖性。你可以自己检查一下这种真实程度 - 可能有些角落的情况并不符合预期。
-
这在调试包时工作得很好,所以dreload的目的是什么,似乎dreload太具侵略性并且在加载某些包如matplotlib时会输出错误。
-
如果使用@Kos方法,请确保定义了c:c = get_config()
-
请记住,无法重新加载C扩展模块(例如来自f2py的模块)。这是在文档中,但我花了一些时间来注意它!
-
@Kos,ipython中的load_ext autoreload和autoreload 2以及deepreload模块有什么区别? ipython.readthedocs.io/en/stable/api/generated/…自动重载是否在后台使用deepreload?
-
不幸的是,这不适用于"当前"脚本。
-
您不应将新值分配给extensions和exec_lines,您应该附加到列表中,以便不覆盖这些列表中分配的现有扩展名和行。我的ipython_config.py包含c.InteractiveShellApp.extensions.append('autoreload'); c.InteractiveShellApp.exec_lines.append('%autoreload 2')
在IPython 0.12(可能更早)中,您可以使用:
1 2
| %load_ext autoreload
%autoreload 2 |
这与pv。的答案基本相同,只是扩展名已重命名,现在使用%load_ext加载。
IPython提供dreload()以递归方式重新加载所有子模块。就个人而言,我更喜欢使用%run() magic命令(尽管它没有执行深度重载,正如John Salvatier在评论中指出的那样)。
-
我认为(不幸的是)%run script.py只重新加载你正在调用的脚本,而不是它导入的包。如果您正在尝试调试正在构建的程序包,这可能会很麻烦。
-
NB。 dreload已在最近的IPython(例如IPython 6.0)中被deepreload取代。
出于某种原因,当您将代码从一个笔记本导入另一个笔记本时,%autoreload和dreload似乎都不适用于这种情况。只有普通的Python reload有效:
基于[1]。
-
reload虽然%autoreload魔法没有
-
在Python 3.4+中,您可以在importlib模块中找到重新加载。 看到这个问题。
-
与%autoreload技术不同,此方法在添加实例方法时有效。 有一个开放的错误报告,为此添加对%autoreload的支持。
http://shawnleezx.github.io/blog/2015/08/03/some-notes-on-ipython-startup-script/
为了避免一次又一次地输入这些魔术函数,可以将它们放入ipython启动脚本(在.ipython / profile_default / startup下使用.py后缀命名。该文件夹下的所有python脚本将根据词法顺序加载),看起来如下:
1 2 3 4 5 6
| from IPython import get_ipython
ipython = get_ipython()
ipython.magic("pylab")
ipython.magic("load_ext autoreload")
ipython.magic("autoreload 2") |
这个怎么样:
1 2 3 4 5 6 7 8 9 10 11 12 13
| 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中使用存储的宏来执行必要的导入和设置以开始在预定义状态下工作。
-
只要你导入的东西是一个模块,它实际上覆盖了from ... import ...和import ... as。它没有涉及的唯一事情是包中的模块没有从它的__init__.py文件加载。对于包,您可以检查模块的__path__属性是否是目录。如果是,则遍历它并递归导入您可以找到的所有模块。我没有写这部分,因为作者没有要求包的解决方案。
-
确实这看起来不错。我想到了这种可能性,同时我希望会有一些内置的功能,即基于此。但是,我不清楚如何使用它。在我发布原始问题之前应该进行一些挖掘之后,我发现了这个扩展。
-
此外,您可以使用pkgutil获取包中的所有子模块,即使包未将子模块导入顶层模块也是如此。 stackoverflow.com/a/1707786/1243926
名为importlib的模块允许访问导入内部。特别是,它提供了函数importlib.reload():
1 2
| import importlib
importlib.reload(my_module) |
与%autoreload相反,importlib.reload()也会重置模块中设置的全局变量。在大多数情况下,这是你想要的。
importlib仅在Python 3.1之后可用。对于旧版本,您必须使用模块imp。
另外一个选项:
1 2 3 4
| $ cat << EOF > ~/.ipython/profile_default/startup/50-autoreload.ipy
%load_ext autoreload
%autoreload 2
EOF |
在Ubuntu 14.04上的ipython和ipython3 v5.1.0上验证。
我重新加载的标准做法是在首次打开IPython后合并两种方法:
1 2 3
| from IPython.lib.deepreload import reload
%load_ext autoreload
%autoreload 2 |
在执行此操作之前加载模块将导致它们无法重新加载,即使使用手动reload(module_name)也是如此。我仍然非常罕见地遇到了无法重新加载的类方法的莫名其妙的问题,我还没有考虑过。
在关于Anaconda的Jupyter笔记本上,这样做:
1 2
| %load_ext autoreload
%autoreload 2 |
产生了消息:
The autoreload extension is already loaded. To reload it, use:
%reload_ext autoreload
看起来最好这样做:
1 2
| %reload_ext autoreload
%autoreload 2 |
版本信息:
The version of the notebook server is 5.0.0 and is running on:
Python 3.6.2 |Anaconda, Inc.| (default, Sep 20 2017, 13:35:58) [MSC v.1900 32 bit (Intel)]