使 IPython 导入我的意思
Make IPython Import What I Mean
我想修改 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
如果香草 IPython 无法做到这一点,我该怎么办
使这项工作? wrapper kernel 是最简单的方法吗?或者这应该直接在核心中使用魔术命令实现吗?
请注意,这与 those kind of question 不同,其中有人希望始终加载预定义模块。我不。因为我不知道我要做什么,我不想加载 everything(我也不想保留 everything 已更新。
注意:现在正在维护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
的环境变量设置为该文件的路径。您根据 OS 设置不同的环境变量(记得更改路径):
- Windows:
setx PYTHONSTARTUP C:\startup.py
在命令提示符下
- Mac/Linux (bash): 将
export PYTHONSTARTUP=$HOME/startup.py
放入你的 ~/.bashrc
这是脚本的实际演示:
我想修改 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
如果香草 IPython 无法做到这一点,我该怎么办 使这项工作? wrapper kernel 是最简单的方法吗?或者这应该直接在核心中使用魔术命令实现吗?
请注意,这与 those kind of question 不同,其中有人希望始终加载预定义模块。我不。因为我不知道我要做什么,我不想加载 everything(我也不想保留 everything 已更新。
注意:现在正在维护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
的环境变量设置为该文件的路径。您根据 OS 设置不同的环境变量(记得更改路径):
- Windows:
setx PYTHONSTARTUP C:\startup.py
在命令提示符下 - Mac/Linux (bash): 将
export PYTHONSTARTUP=$HOME/startup.py
放入你的~/.bashrc
这是脚本的实际演示: