2

我在 Python 中定义了以下(嵌入式)shell:

from IPython.config.loader import Config
cfg = Config()
prompt_config = cfg.PromptManager
prompt_config.in_template = 'N.In <\\#>: '
prompt_config.in2_template = '   .\\D.: '
prompt_config.out_template = 'N.Out<\\#>: '
banner_msg = ("\n**Nested Interpreter:\n"
"Hit Ctrl-D to exit interpreter and continue program.\n"
"Note that if you use %kill_embedded, you can fully deactivate\n"
"This embedded instance so it will never turn on again")
exit_msg = '**Leaving Nested interpreter'

from IPython.frontend.terminal.embed import InteractiveShellEmbed
ipshell = InteractiveShellEmbed(config=cfg, banner1=banner_msg, exit_msg=exit_msg)

我希望我的程序在出现异常时自动将我放入该 shell,在异常发生的范围内。

我尝试过:

def excepthook(type, value, traceback):
    ipshell(msg)

sys.excepthook = excepthook

但这似乎不起作用(我只是得到标准的回溯)。此外,理想情况下,最好是:

  1. IPython 打印常规回溯
  2. 然后把我放到一个 IPython shell

如果我上面写的代码有效,它只会把我放到一个 IPython shell 中,而不是打印回溯。

更新1:

我在这里读到,当从 IPython 运行代码时,IPython 负责捕获所有异常,并且可能无法直接覆盖sys.excepthook(). 如果是这种情况,我如何让 IPythonipshell()在发生异常的范围内以及在它打印回溯之后执行其他异常挂钩(例如 my )?

更新 2:

开发列表中似乎有一个线程在讨论这个问题:ipython 中的excepthook-like behavior。显然有一个功能set_custom_exc可以解决这个问题,但我不确定如何将其插入到我的ipshell().

4

2 回答 2

1

我认为几乎不可能让异常一直通过调用堆栈来找出是否有人最终会捕获并处理它,然后返回到它最初引发的范围。当异常弹出时,原始范围已经消失。

您最好的选择可能是将您希望 shell 出现的所有部分包装起来,以使用专用块处理异常,try ... except如下所示:

try: 
   pass # stuff that may raise an exception
except KeyboardInterrupt:
   # some exception you want to handle
   raise 
except SystemExit:
   # another exception you want to handle
   raise 
except: 
   # get a hand on any unhandled exception
   ipshell(traceback.format_exc())

(不确定这是否可以更优雅地实现。我也会对更好的解决方案非常感兴趣!)

于 2013-04-02T11:17:22.333 回答
1

在我的 ipython shell 中定义以下内容似乎可以满足您的要求:

def custom_exc(shell, etype, evalue, tb, tb_offset=None):
    shell.showtraceback((etype, evalue, tb), tb_offset=tb_offset)
    ipshell()

get_ipython().set_custom_exc((Exception,), custom_exc)
于 2013-04-02T18:04:41.333 回答