我想默认修改IPython如何处理导入错误。当我在IPython shell中对原型进行原型化时,我通常会忘记首先导入os
,re
或我需要的任何东西。前几个陈述通常遵循这种模式:
In [1]: os.path.exists("~/myfile.txt")
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-1-0ffb6014a804> in <module>()
----> 1 os.path.exists("~/myfile.txt")
NameError: name 'os' is not defined
In [2]: import os
In [3]: os.path.exists("~/myfile.txt")
Out[3]: False
当然,这是我的坏习惯, 当然,在一个有意义的脚本或真实程序中, 但在shell中,我宁愿跟随IPython DWIM原则,至少尝试导入我想要使用的内容。
In [1]: os.path.exists("~/myfile.txt")
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-1-0ffb6014a804> in <module>()
----> 1 os.path.exists("~/myfile.txt")
NameError: name 'os' is not defined
Catching this for you and trying to import "os" … success!
Retrying …
---------------------------------------------------------------------------
Out[1]: False
如果使用vanilla IPython无法做到这一点,我该怎么办呢 使这项工作? wrapper kernel是最简单的前进方式吗?或者应该使用魔术命令直接在核心中实现?
注意,这与those kind of question不同,其中有人想要始终加载预定义的模块。我没有。因为我不知道自己将要做什么,而且我不想加载所有内容(我也不想保留所有内容的列表更新。
答案 0 :(得分:10)
注意:现在正在维护on Github。从那里下载最新版本的脚本!
我开发了一个脚本,通过set_custom_exc
绑定到IPython的异常处理。如果有NameError
,它会使用正则表达式来查找您尝试使用的模块,然后尝试导入它。然后它会运行您尝试再次调用的函数。这是代码:
import sys, IPython, colorama # <-- colorama must be "pip install"-ed
colorama.init()
def custom_exc(shell, etype, evalue, tb, tb_offset=None):
pre = colorama.Fore.CYAN + colorama.Style.BRIGHT + "AutoImport: " + colorama.Style.NORMAL + colorama.Fore.WHITE
if etype == NameError:
shell.showtraceback((etype, evalue, tb), tb_offset) # Show the normal traceback
import re
try:
# Get the name of the module you tried to import
results = re.match("name '(.*)' is not defined", str(evalue))
name = results.group(1)
try:
__import__(name)
except:
print(pre + "{} isn't a module".format(name))
return
# Import the module
IPython.get_ipython().run_code("import {}".format(name))
print(pre + "Imported referenced module \"{}\", will retry".format(name))
except Exception as e:
print(pre + "Attempted to import \"{}\" but an exception occured".format(name))
try:
# Run the failed line again
res = IPython.get_ipython().run_cell(list(get_ipython().history_manager.get_range())[-1][-1])
except Exception as e:
print(pre + "Another exception occured while retrying")
shell.showtraceback((type(e), e, None), None)
else:
shell.showtraceback((etype, evalue, tb), tb_offset=tb_offset)
# Bind the function we created to IPython's exception handler
IPython.get_ipython().set_custom_exc((Exception,), custom_exc)
您可以在启动IPython提示时自动运行,方法是将其保存到某处,然后将名为PYTHONSTARTUP
的环境变量设置为此文件的路径。您可以根据操作系统设置不同的环境变量(请记住改变路径):
setx PYTHONSTARTUP C:\startup.py
export PYTHONSTARTUP=$HOME/startup.py
放入~/.bashrc
以下是该剧本的演示: