【问题标题】:Opening an IPython shell on any (uncaught) exception [duplicate]在任何(未捕获的)异常上打开 IPython shell [重复]
【发布时间】:2013-04-01 21:44:58
【问题描述】:

我在 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:

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

更新 2:

开发列表中似乎有一个帖子讨论这个问题:excepthook-like behavior in ipython。显然有一个函数 set_custom_exc 可以解决这个问题,但我不确定如何将其插入我的 ipshell()

【问题讨论】:

  • 只是为了明确一点:您希望嵌入式 shell 在第一次引发异常的范围内(与第一次捕获异常的位置相反)?
  • 这是另一个问题的答案,可以完成您想要的,包括保留发生异常的大部分上下文。比 PDB 有用得多。 stackoverflow.com/a/26707499/2683747

标签: python debugging ipython


【解决方案1】:

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

您最好的选择可能是使用专用的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())

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

【讨论】:

  • 这是我找到的最佳解决方案:stackoverflow.com/a/26707499/2683747
  • 感谢您指出这一点。尽管两者都很老,但我投票将其标记为该线程的副本,因为它似乎提供了更多/更好的解决方案......
【解决方案2】:

在我的 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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-17
    • 1970-01-01
    • 2014-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多