抓取 PyQt 中的任何异常
Grab any exception in PyQt
我在 PyQt 中创建了一个 GUI 应用程序,我想与很多人分享。有时我会遇到意想不到的异常并且我认为这是理所当然的 - 在每次异常之后我都会改进我的代码并且它会变得越来越好。
我使用一个记录器来记录这些异常和 PyQt 静默异常的特殊挂钩。我的代码如下所示:
记录器
def setLogger(level=logging.DEBUG,
name="my_logger",
file=join("src", "log.out")):
logger = logging.getLogger(name)
logger.setLevel(level)
# console logger
ch = logging.StreamHandler()
console_lvl = logging.DEBUG
ch.setLevel(console_lvl)
formatter = logging.Formatter('%(message)s')
ch.setFormatter(formatter)
#file logger
fh = logging.FileHandler(file)
fh.setLevel(level)
formatter = logging.Formatter(
'%(asctime)s :: %(name)s - %(message)s',
datefmt='%m/%d/%Y %I:%M:%S %p')
fh.setFormatter(formatter)
logger.addHandler(ch)
logger.addHandler(fh)
return logger
2 个典型的 class GUI
class MainWindow(QtGui.QMainWindow):
def __init__(self):
self.logger = setLogger(name='main_window')
[...]
class UploadDialog(QtGui.QDialog):
def __init__(self):
self.logger = setLogger(name='upload_dialog')
[...]
等等
PyQt 有其沉默的异常 - 异常发生但程序保持 运行。我针对这种情况使用了特殊的钩子(在某处看到过,这不是我的代码)
import sys
sys._excepthook = sys.excepthook
def exception_hook(exctype, value, traceback):
sys._excepthook(exctype, value, traceback)
sys.exit(1)
现在我想捕获任何异常,所以我的程序的用户在发生任何崩溃时只需将他们的 log.out 发送给我,我就会看到完整日志。
我是从这样的事情开始的。
try:
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
except Exception:
logger.exception("MainWindow exception")
我工作得很好,直到 UploadDialog 内部出现异常。什么都没有 'recorded'。所以我只是做了:
#inside MainWindow class
def runDialog(self):
try:
dialog = UploadDialog()
dialog.exec_()
except Exception:
self.logger.exception("Dialog exception")
sys.exit(1)
再次,一切正常,直到 WorkThread 内部出现异常(继承自 QThread class 用于后台上传)。再一次。
#inside UploadDialog
def upload(self):
# initialized as self.task = WorkThread()
try:
self.task.start()
except Exception:
self.logger.exception("Exception in WorkThread")
然后不是在 WorkThread 启动之后而是在初始化时引发了异常,所以
class UploadDialog(QtGui.QDialog):
def __init__(self):
try:
self.task = WorkThread()
except Exception:
self.logger.exception("Exception in WorkThread")
在这里我只是抬起头对自己尖叫 - "STOP IT. YOU'RE DOING IT WRONG. It's not pythonic, it's dirty, it makes my eyes bleed"。
所以,我想问 - 是否有任何优雅和 pythonic 的方式来绝对捕获在 PyQt 应用程序中用一个 try...except
块引发的任何异常?
使用 excepthook 的目的是让您可以监视 所有 程序引发的异常,并集中处理它们。
所以你应该摆脱大部分 try/except
块,并在 excepthook 函数中记录异常。我说"most",因为你可能会受到bug 1230540, where sys.excepthook
is not called correctly outside of the main thread. See the tracker thread for some workarounds for that, or this SO answer的影响。
我在 PyQt 中创建了一个 GUI 应用程序,我想与很多人分享。有时我会遇到意想不到的异常并且我认为这是理所当然的 - 在每次异常之后我都会改进我的代码并且它会变得越来越好。
我使用一个记录器来记录这些异常和 PyQt 静默异常的特殊挂钩。我的代码如下所示:
记录器
def setLogger(level=logging.DEBUG,
name="my_logger",
file=join("src", "log.out")):
logger = logging.getLogger(name)
logger.setLevel(level)
# console logger
ch = logging.StreamHandler()
console_lvl = logging.DEBUG
ch.setLevel(console_lvl)
formatter = logging.Formatter('%(message)s')
ch.setFormatter(formatter)
#file logger
fh = logging.FileHandler(file)
fh.setLevel(level)
formatter = logging.Formatter(
'%(asctime)s :: %(name)s - %(message)s',
datefmt='%m/%d/%Y %I:%M:%S %p')
fh.setFormatter(formatter)
logger.addHandler(ch)
logger.addHandler(fh)
return logger
2 个典型的 class GUI
class MainWindow(QtGui.QMainWindow):
def __init__(self):
self.logger = setLogger(name='main_window')
[...]
class UploadDialog(QtGui.QDialog):
def __init__(self):
self.logger = setLogger(name='upload_dialog')
[...]
等等
PyQt 有其沉默的异常 - 异常发生但程序保持 运行。我针对这种情况使用了特殊的钩子(在某处看到过,这不是我的代码)
import sys
sys._excepthook = sys.excepthook
def exception_hook(exctype, value, traceback):
sys._excepthook(exctype, value, traceback)
sys.exit(1)
现在我想捕获任何异常,所以我的程序的用户在发生任何崩溃时只需将他们的 log.out 发送给我,我就会看到完整日志。
我是从这样的事情开始的。
try:
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
except Exception:
logger.exception("MainWindow exception")
我工作得很好,直到 UploadDialog 内部出现异常。什么都没有 'recorded'。所以我只是做了:
#inside MainWindow class
def runDialog(self):
try:
dialog = UploadDialog()
dialog.exec_()
except Exception:
self.logger.exception("Dialog exception")
sys.exit(1)
再次,一切正常,直到 WorkThread 内部出现异常(继承自 QThread class 用于后台上传)。再一次。
#inside UploadDialog
def upload(self):
# initialized as self.task = WorkThread()
try:
self.task.start()
except Exception:
self.logger.exception("Exception in WorkThread")
然后不是在 WorkThread 启动之后而是在初始化时引发了异常,所以
class UploadDialog(QtGui.QDialog):
def __init__(self):
try:
self.task = WorkThread()
except Exception:
self.logger.exception("Exception in WorkThread")
在这里我只是抬起头对自己尖叫 - "STOP IT. YOU'RE DOING IT WRONG. It's not pythonic, it's dirty, it makes my eyes bleed"。
所以,我想问 - 是否有任何优雅和 pythonic 的方式来绝对捕获在 PyQt 应用程序中用一个 try...except
块引发的任何异常?
使用 excepthook 的目的是让您可以监视 所有 程序引发的异常,并集中处理它们。
所以你应该摆脱大部分 try/except
块,并在 excepthook 函数中记录异常。我说"most",因为你可能会受到bug 1230540, where sys.excepthook
is not called correctly outside of the main thread. See the tracker thread for some workarounds for that, or this SO answer的影响。