为什么Python中的装饰器式上下文管理器不会在Tkinter窗口中捕获异常?

时间:2015-07-02 07:43:48

标签: python exception-handling tkinter

通过contextlib有一个带有装饰器生成的上下文管理器的简单代码。当我按下按钮异常时,上下文管理器不处理。为什么?

from Tkinter import Tk, Button
from contextlib import contextmanager


def close_window(): 
    window.destroy()
    raise Exception


@contextmanager
def safe():
    try:
        yield
    except:
        print 'Exception catched'

with safe():
    window = Tk()
    button = Button(window, text='Press me', command=close_window)
    button.pack()
    window.mainloop()

为什么异常仍然会提高?

UPD我使用Python 2.7

1 个答案:

答案 0 :(得分:3)

Tkinter主进程循环不会被异常关闭,也不会进一步传播它们。因此,异常永远不会到达with语句(因为tkinter本身捕获并报告异常然后停止执行)。

您需要创建一个装饰器来捕获这些异常并记录它们或执行您想要做的任何逻辑。

示例 -

from Tkinter import Tk, Button
from contextlib import contextmanager

class exceptioncatcher: # <---the decorator
    def __init__(self, function):
        self.function = function
    def __call__(self, *args, **kwargs):
        try:
            return self.function(*args, **kwargs)
        except Exception:
            print 'Exception catched1'


@exceptioncatcher
def close_window(): 
    window.destroy()
    raise Exception


@contextmanager
def safe():
    try:
        yield
    except Exception:
        print 'Exception catched'

with safe():
    window = Tk()
    button = Button(window, text='Press me', command=close_window)
    button.pack()
    window.mainloop()

使用上面的代码,当我点击Press按钮时,它会为我记录Exception catched1并退出。

此外,except:你应该给你想要捕获的异常(或至少except Exception:)是不好的。

相关问题