捕获 PyQt 中的任何异常

问题描述 投票:0回答:1

我在 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

GUI 中的 2 个典型类

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 内引发异常。没有任何内容被“记录”。所以我就这么做了:

#inside MainWindow class
def runDialog(self):
    try:
        dialog = UploadDialog()
        dialog.exec_()
    except Exception:
        self.logger.exception("Dialog exception")
        sys.exit(1)

再次,一切正常,直到WorkThread内部出现异常(继承自QThread类,用于后台上传)。又来了一次。

#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")

在这里,我只是抬起头对自己尖叫 - “停下来。你做错了。这不是蟒蛇式的,它很脏,它让我的眼睛流血”。

所以,我问 - 有没有一种优雅且Python式的方法来捕获在 PyQt 应用程序中用一个

try...except
块引发的绝对异常?

python python-3.x exception logging pyqt4
1个回答
4
投票

使用 excepthook 的目的是让您可以监视程序引发的所有异常,并集中处理它们。

因此,您应该删除大部分

try/except
块,并将异常记录在 excepthook 函数中。我说“大多数”,因为你可能会受到 bug 1230540 的影响,其中
sys.excepthook
在主线程之外没有被正确调用。请参阅跟踪器线程以获取一些解决方法,或者这个SO答案

(PS:线程问题已在 Python-3.8 中修复。请参阅这个答案)。

© www.soinside.com 2019 - 2024. All rights reserved.