gpt4 book ai didi

Python3 : purge exception chain?

转载 作者:太空宇宙 更新时间:2023-11-03 18:50:23 26 4
gpt4 key购买 nike

我试图在 except: block 中引发异常,但解释器试图提供帮助并“强制”打印堆栈跟踪。有可能避免这种情况吗?

一些背景信息:我正在玩弄 urwid,一个 TUI library对于 python 。用户界面通过调用 urwid.MainLoop.run() 启动,并通过提升 urwid.ExitMainLoop() 结束。到目前为止,这工作得很好,但是当引发另一个异常时会发生什么?例如。当我捕获KeyboardInterrupt(urwid MainLoop 没有)时,我会进行一些清理并希望通过引发适当的异常来结束用户界面。但这会导致屏幕上充满堆栈跟踪。

一些小研究表明 python3 会记住链式异常,并且可以通过“原因”显式引发异常:从 A() 引发 B()。我学习了一些更改或附加有关引发的异常的数据的方法,但我发现没有办法“禁用”此功能。我想避免打印堆栈跟踪和诸如 The 上述异常是...的直接原因 之类的行,而只是在 except: 中引发接口(interface)结束异常> 像我在外面一样阻止。

这可能吗,还是我做的事情根本就是错误的?

编辑:这是一个类似于我当前架构的示例,导致了同样的问题:

#!/usr/bin/env python3
import time

class Exit_Main_Loop(Exception):
pass

# UI main loop
def main_loop():
try:
while True:
time.sleep(0.1)
except Exit_Main_Loop as e:
print('Exit_Main_Loop')
# do some UI-related clean up

# my main script
try:
main_loop()
except KeyboardInterrupt as e:
print('KeyboardInterrupt')
# do some clean up
raise Exit_Main_Loop() # signal the UI to terminate

不幸的是,我也无法将 main_loop 更改为除 KeyboardInterrupt 之外的内容。有解决这个问题的模式吗?

最佳答案

我还是不太明白你的解释,但是从代码来看:

try:
main_loop()
except KeyboardInterrupt as e:
print('KeyboardInterrupt')
# do some clean up
raise Exit_Main_Loop() # signal the UI to terminate

main_loop 不可能看到 Exit_Main_Loop() 异常。当您到达 KeyboardInterrupt 句柄时,main_loop 保证已经完成(在本例中,由于未处理的 KeyboardInterrupt),所以它的异常处理程序不再事件。

因此,发生的情况是您引发了一个没有人捕获的新异常。当异常到达代码顶部而未被处理时,Python 会通过打印回溯并退出来自动处理它。

如果您想将一种类型的异常转换为另一种类型的异常,以便 main_loop 可以处理它,您必须在 try 的某个内部执行此操作 block 。

你说:

Unfortunately I can't change main_loop to except KeyboardInterrupt as well.

如果这是真的,那么您的问题就没有真正的答案......但我不确定除了您创建的问题之外,一开始还存在其他问题。只需从代码中删除 Exit_Main_Loop() ,它不是已经完成了您想要的操作吗?如果您只是想阻止 Python 打印回溯并退出,这将为您解决。

<小时/>

如果确实存在问题,例如,main_loop 代码有一些清理代码,无论如何您都需要执行这些代码,但它不会被执行,因为它不处理KeyboardInterrupt——有两种方法可以解决这个问题。

<小时/>

首先,如signal文档解释:

The signal.signal() function allows to define custom handlers to be executed when a signal is received. A small number of default handlers are installed: … SIGINT is translated into a KeyboardInterrupt exception.

因此,您所要做的就是用不同的处理程序替换默认处理程序:

def handle_sigint(signum, frame):
raise ExitMainLoop()
signal.signal(signal.SIGINT, handle_sigint)

只要在启动 main_loop 之前执行此操作,就应该没问题。请记住,线程程序和 Windows 存在一些限制,但如果这些限制都不适用,那么您就很成功了; ctrl-C 将触发 ExitMainLoop 异常,而不是 KeyboardInterrupt,因此主循环将处理它。 (您可能还想在包装器代码中添加一个 except ExitMainLoop: block ,以防main_loop之外出现异常。但是,您可以轻松编写一个 contextmanager 来设置和恢复对 main_loop 的调用周围的信号,因此没有任何外部代码可能会引发该信号。)

<小时/>

或者,即使您无法编辑 main_loop 源代码,您也可以在运行时对其进行猴子修补。如果不知道代码是什么样的,就不可能准确解释如何做到这一点,但几乎总有一种方法可以做到这一点。

关于Python3 : purge exception chain?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18499423/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com