优雅地处理 PyQt4 中被抑制(未处理)的异常
Gracefully handle suppressed (unhandled) exceptions in PyQt4
问题:
我正在尝试找出处理通常被 PyQt 抑制的未处理异常的最佳方法。
我现在的解决方案是用以下装饰器装饰适当的方法
def handleExceptions(func):
"""
Decorator: create and show message box for every unhandled exception that
reaches the decorator
"""
@functools.wraps(func)
def decorator(self):
try:
func(self)
except Exception as error:
# ...
if errBox.exec_() == QMessageBox.Ok:
try:
self.closeApp()
except AttributeError:
exit()
return decorator
但是,只有 none 的修饰方法需要比 self
更多的参数时,此解决方案才有效。我试过像这样扩展装饰器
...
def decorator(self, *args)
try:
func(self, *args)
...
这允许使用一个或多个参数调用函数(包括self
)。不幸的是,此代码中断了对除 self
之外不需要参数的方法的访问,后者失败并显示消息 TypeError: method() takes 1 positional argument but 2 were given
.
使用调试器后,我发现 *args
中的第二个参数似乎是一个布尔值 (False
)。
问题:
- 为什么要传递这个附加参数?
- 如何修改装饰器以允许使用不同参数长度的函数?
- 这甚至是处理异常的好方法吗?如果有人能告诉我在 PyQt 中处理未处理异常的常用方法,我将不胜感激。
我查找了其他解决方案,如 this one(我并不完全理解)并尝试实施它们但没有成功(它要么像我的那样抛出异常,要么完全破坏装饰方法)。
提前致谢!
虽然我同意 excepthook 可能是解决方法的评论,但我曾经做过类似的事情:
def handle_exception_decorator(exceptions_to_catch = (ValueError, IndexError, TypeError), return_on_fail=False):
def wrap(fn):
@functools.wraps(fn)
def f(*args, **kwargs):
try:
return fn(*args, **kwargs)
except tuple(exceptions_to_catch) as e:
# handle the exception here:
return return_on_fail
return f
return wrap
用以下方式装饰您的方法:
@handle_exception_decorator
或
@handle_exception_decorator(exceptions_to_catch=(AnExceptionType,))
或
@handle_exception_decorator(exceptions_to_catch=(Exception,), return_on_fail=7)
等...
编辑:哦,实际上我认为你的问题是因为你正在装饰的方法是一个连接到信号的插槽,而你的插槽忽略了信号发出的参数之一。解决这个问题的唯一方法是更新装饰函数以接受一个可选的关键字参数,该参数采用信号发出的参数。你当然不必在你的方法中使用它,你只需要方法签名来匹配信号将发出的内容(Qt 通常会优雅地处理这个,但是像这样的装饰器会把事情搞砸!)
问题:
我正在尝试找出处理通常被 PyQt 抑制的未处理异常的最佳方法。
我现在的解决方案是用以下装饰器装饰适当的方法
def handleExceptions(func):
"""
Decorator: create and show message box for every unhandled exception that
reaches the decorator
"""
@functools.wraps(func)
def decorator(self):
try:
func(self)
except Exception as error:
# ...
if errBox.exec_() == QMessageBox.Ok:
try:
self.closeApp()
except AttributeError:
exit()
return decorator
但是,只有 none 的修饰方法需要比 self
更多的参数时,此解决方案才有效。我试过像这样扩展装饰器
...
def decorator(self, *args)
try:
func(self, *args)
...
这允许使用一个或多个参数调用函数(包括self
)。不幸的是,此代码中断了对除 self
之外不需要参数的方法的访问,后者失败并显示消息 TypeError: method() takes 1 positional argument but 2 were given
.
使用调试器后,我发现 *args
中的第二个参数似乎是一个布尔值 (False
)。
问题:
- 为什么要传递这个附加参数?
- 如何修改装饰器以允许使用不同参数长度的函数?
- 这甚至是处理异常的好方法吗?如果有人能告诉我在 PyQt 中处理未处理异常的常用方法,我将不胜感激。
我查找了其他解决方案,如 this one(我并不完全理解)并尝试实施它们但没有成功(它要么像我的那样抛出异常,要么完全破坏装饰方法)。
提前致谢!
虽然我同意 excepthook 可能是解决方法的评论,但我曾经做过类似的事情:
def handle_exception_decorator(exceptions_to_catch = (ValueError, IndexError, TypeError), return_on_fail=False):
def wrap(fn):
@functools.wraps(fn)
def f(*args, **kwargs):
try:
return fn(*args, **kwargs)
except tuple(exceptions_to_catch) as e:
# handle the exception here:
return return_on_fail
return f
return wrap
用以下方式装饰您的方法:
@handle_exception_decorator
或
@handle_exception_decorator(exceptions_to_catch=(AnExceptionType,))
或
@handle_exception_decorator(exceptions_to_catch=(Exception,), return_on_fail=7)
等...
编辑:哦,实际上我认为你的问题是因为你正在装饰的方法是一个连接到信号的插槽,而你的插槽忽略了信号发出的参数之一。解决这个问题的唯一方法是更新装饰函数以接受一个可选的关键字参数,该参数采用信号发出的参数。你当然不必在你的方法中使用它,你只需要方法签名来匹配信号将发出的内容(Qt 通常会优雅地处理这个,但是像这样的装饰器会把事情搞砸!)