让IPython导入我的意思

时间:2016-03-20 09:50:27

标签: python ipython ipython-magic

我想默认修改IPython如何处理导入错误。当我在IPython shell中对原型进行原型化时,我通常会忘记首先导入osre或我需要的任何东西。前几个陈述通常遵循这种模式:

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不同,其中有人想要始终加载预定义的模块。我没有。因为我不知道自己将要做什么,而且我不想加载所有内容(我也不想保留所有内容的列表更新。

1 个答案:

答案 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的环境变量设置为此文件的路径。您可以根据操作系统设置不同的环境变量(请记住改变路径):

  • Windows:命令提示符中的setx PYTHONSTARTUP C:\startup.py
  • Mac / Linux(bash):将export PYTHONSTARTUP=$HOME/startup.py放入~/.bashrc

以下是该剧本的演示:

Demo