我在 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
但这似乎不起作用(我只是得到标准回溯)。另外,理想情况下最好:
- IPython 打印常规回溯
- 然后将我放入 IPython shell
如果我上面编写的代码有效,它只会将我放入 IPython shell,而不打印回溯。
更新 1:
我已阅读here当从 IPython 运行代码时,IPython 负责捕获所有异常,并且可能无法直接覆盖 sys.excepthook()
。如果是这种情况,我如何让 IPython 在异常发生的范围内以及打印回溯之后执行其他异常 Hook (例如我的 ipshell()
)?
更新 2:
开发列表中似乎有一个线程讨论此问题:excepthook-like behavior in ipython 。显然有一个函数 set_custom_exc
就可以解决这个问题,但我不确定如何将其插入到我的 ipshell()
中.
最佳答案
我认为不太可能让异常一路通过调用栈,看看最后是否有人会捕获并处理它,然后返回到它第一次引发的作用域。当异常从其中弹出时,原始范围就消失了。
您最好的选择可能是使用专用的 try ... except
block 来包装您希望 shell 处理异常的所有部分,如下所示:
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())
(不确定这是否可以更优雅地实现。我也对更好的解决方案非常感兴趣!)
关于python - 在任何(未捕获的)异常上打开 IPython shell,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15752437/