Python3:清除异常链?

Python3:清除异常链?,python,exception,python-3.x,urwid,Python,Exception,Python 3.x,Urwid,我试图在except:块中引发异常,但解释器试图提供帮助,并“强制”打印堆栈跟踪。有可能避免这种情况吗 一点背景信息: 我在玩弄urwid,一个python的工具。用户界面通过调用urwid.MainLoop.run()启动,并通过调用urwid.ExitMainLoop()结束。到目前为止,这一切正常,但当引发另一个异常时会发生什么?例如,当我捕获键盘中断(urwid MainLoop没有)时,我会进行一些清理,并希望通过引发适当的异常来结束用户界面。但这会导致屏幕上布满堆栈痕迹 一些小规模的

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

一点背景信息: 我在玩弄urwid,一个python的工具。用户界面通过调用
urwid.MainLoop.run()
启动,并通过调用
urwid.ExitMainLoop()
结束。到目前为止,这一切正常,但当引发另一个异常时会发生什么?例如,当我捕获
键盘中断
(urwid MainLoop没有)时,我会进行一些清理,并希望通过引发适当的异常来结束用户界面。但这会导致屏幕上布满堆栈痕迹

一些小规模的研究表明,python3能够记住链式异常,并且可以显式地使用“原因”引发异常:
raiseb()from a()
。我学习了一些方法来更改或附加有关引发的异常的数据,但我没有找到“禁用”此功能的方法。我希望避免打印堆栈跟踪和行,如
上面的异常是…
的直接原因,只需在
中引发接口结束异常,除了:
块,就像我在块之外一样

这是可能的还是我做错了什么

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

#!/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

不幸的是,我不能将
主循环
更改为除
键盘中断
之外的其他内容。有解决这个问题的模式吗?

我仍然不太理解您的解释,但从代码:

try:
    main_loop()
except KeyboardInterrupt as e:
    print('KeyboardInterrupt')
    # do some clean up
    raise Exit_Main_Loop()      # signal the UI to terminate
main\u loop
不可能看到
Exit\u main\u loop()
异常。当您到达
键盘中断
句柄时,
主循环
保证已经完成(在这种情况下,由于未处理的
键盘中断
),因此其异常处理程序不再处于活动状态

所以,所发生的是,你提出了一个新的异常,没有人发现。当异常到达代码顶部而未被处理时,Python会通过打印回溯并退出来自动处理它

如果要将一种类型的异常转换为另一种类型,以便
main\u循环
能够处理它,则必须在
try
块中的某个位置执行该操作

你说:

不幸的是,除了键盘中断,我不能将主循环更改为

如果这是真的,你的问题就没有真正的答案……但我不确定一开始是否有问题,除了你创造的问题。只需从代码中删除
Exit\u Main\u Loop()?如果您只是试图阻止Python打印回溯并退出,这将为您解决问题


如果确实存在问题,例如,
main_循环
代码中有一些清理代码,无论发生什么情况,都需要执行这些代码,而它没有执行,因为它不处理
键盘中断
——有两种方法可以解决这个问题


首先,正如文件所解释的:

signal.signal()
函数允许定义接收信号时要执行的自定义处理程序。安装了少量默认处理程序:…
SIGINT
被转换为
键盘中断
异常

因此,您只需将默认处理程序替换为其他处理程序:

def handle_sigint(signum, frame):
    raise ExitMainLoop()
signal.signal(signal.SIGINT, handle_sigint)
在开始
main\u循环
之前,只需这样做,您就会没事了。请记住,线程程序和Windows都有一些限制,但如果这些限制都不适用,那么你就是黄金;ctrl-C将触发
ExitMainLoop
异常,而不是
键盘中断
,因此主循环将处理该异常。(您可能还希望在包装器代码中添加一个除ExitMainLoop:
之外的
块,以防在
main\u循环
之外出现异常。但是,您可以轻松编写一个
contextmanager
,设置并恢复对
main\u循环
的调用周围的信号,因此没有任何外部代码可能出现异常。)(她说。)



或者,即使无法编辑
main\u循环
源代码,也可以在运行时对其进行monkeypatch。如果不知道代码是什么样子,就不可能准确地解释如何做到这一点,但几乎总是有办法做到的。

我仍然不太理解您的解释,但从代码中:

try:
    main_loop()
except KeyboardInterrupt as e:
    print('KeyboardInterrupt')
    # do some clean up
    raise Exit_Main_Loop()      # signal the UI to terminate
main\u loop
不可能看到
Exit\u main\u loop()
异常。当您到达
键盘中断
句柄时,
主循环
保证已经完成(在这种情况下,由于未处理的
键盘中断
),因此其异常处理程序不再处于活动状态

所以,所发生的是,你提出了一个新的异常,没有人发现。当异常到达代码顶部而未被处理时,Python会通过打印回溯并退出来自动处理它

如果要将一种类型的异常转换为另一种类型,以便
main\u循环
能够处理它,则必须在
try
块中的某个位置执行该操作

你说:

不幸的是,除了键盘中断,我不能将主循环更改为

如果这是真的,你的问题就没有真正的答案……但我不确定一开始是否有问题,除了你创造的问题。只需从代码中删除
Exit\u Main\u Loop()?如果您只是试图阻止Python打印回溯并退出,这将为您解决问题


如果确实存在问题,例如,
main_循环
代码中有一些清理代码,无论发生什么情况,都需要执行这些代码,它是n