我正在通过运行魔法在 ipython 中运行一个脚本:
%run myscript.py
Run Code Online (Sandbox Code Playgroud)
这个脚本导入了我编写的各种模块,我经常在运行之间更改这些模块。我想自动重新加载这些模块,而不必重新启动 ipython。在stackoverflow和其他地方有很多问题推荐
%load_ext autoreload
%autoreload 2
Run Code Online (Sandbox Code Playgroud)
也许还有
%aimport <your module>
Run Code Online (Sandbox Code Playgroud)
很好地投入。但这根本行不通。深度重载是否超出了自动重载的能力?是否有其他方法可以删除所有加载的模块,或者静默重启 ipython 依赖的 python 后台进程?
编辑:玩了更多这个,似乎自动重装失败有点微妙。可能(我还不是 100% 确定)自动重新加载仅在我的模块的 __init__.py 正在执行时才会失败from .<some file in the module> import *,而不是按名称导入每个成员。我也尝试过这种%reset魔法,但这似乎只是清空了命名空间,并没有清除缓存的模块。
顺便说一句,Spyder 能够强制重新加载模块,但我不确定这是如何完成的(围绕 ipython 的某种包装会重新启动进程?)
我抬头Spyder的解决方案,它主要采用del上sys.modules。下面我稍微修改了我在 中找到的代码,~/anaconda3/lib/python3.6/site-packages/spyder/utils/site/sitecustomize.py并将其放在一个名为 的模块中reloader.py:
import sys
def _is_module_deletable(modname, modpath):
if modname.startswith('_cython_inline'):
# Don't return cached inline compiled .PYX files
return False
for path in [sys.prefix]:
if modpath.startswith(path):
return False
else:
return set(modname.split('.'))
def clear():
"""
Del user modules to force Python to deeply reload them
Do not del modules which are considered as system modules, i.e.
modules installed in subdirectories of Python interpreter's binary
Do not del C modules
"""
log = []
for modname, module in list(sys.modules.items()):
modpath = getattr(module, '__file__', None)
if modpath is None:
# *module* is a C module that is statically linked into the
# interpreter. There is no way to know its path, so we
# choose to ignore it.
continue
if modname == 'reloader':
# skip this module
continue
modules_to_delete = _is_module_deletable(modname, modpath)
if modules_to_delete:
log.append(modname)
del sys.modules[modname]
print("Reloaded modules:\n\n%s" % ", ".join(log))
Run Code Online (Sandbox Code Playgroud)
现在只是做import reloader然后打电话reloader.clear()
| 归档时间: |
|
| 查看次数: |
870 次 |
| 最近记录: |