抢占PyQt中的任何异常 [英] Grab any exception in PyQt

查看:148
本文介绍了抢占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

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

在这里,我只是低下头,对自己尖叫着-别再说了.您做错了.它不是pythonic,它很脏,它使我的眼睛流血."

所以,我想问-在PyQt应用程序中使用一个try...except块引发的异常中,是否有任何优雅而pythonic的方法来绝对捕获任何异常?

解决方案

使用excepthook的目的是,您可以监视程序所引发的所有异常,并进行集中处理. /p>

因此,您应该摆脱大多数try/except块,并在excepthook函数内记录异常.我说最多"是因为您可能会受到错误1230540 的影响,其中未调用sys.excepthook正确地位于主线程之外.有关某些解决方法,请参见跟踪器线程,或此SO答案.

I've created an GUI app in PyQt, which I want to share with many people. Sometimes I get unexpected exceptions and I take it for granted - after every exception I improve my code and it gets better and better.

I use a logger for recording these exceptions and special hook for PyQt silenced exceptions. My code looks like this:

Logger

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 typical classes in 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')
    [...]

and so on
PyQt has its silenced exceptions - exception occurs but program keeps running. I use the special hook for this situation (have seen it somewhere, this is not my code)

import sys
sys._excepthook = sys.excepthook

def exception_hook(exctype, value, traceback):
    sys._excepthook(exctype, value, traceback)
    sys.exit(1)

And now I want to grab any exception, so the users of my program in case of any crash could just send me their log.out and I would see the full log.

I've started from something like this.

try:
    app = QtGui.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())
except Exception:
    logger.exception("MainWindow exception")

I worked well, until an exception was raised inside UploadDialog. Nothing was 'recorded'. So I just did:

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

Again, everything was OK, until an exception was rised inside WorkThread (Inherited from QThread class for background upload). And again.

#inside UploadDialog
def upload(self):
    # initialized as self.task = WorkThread()
    try:
        self.task.start()
    except Exception:
        self.logger.exception("Exception in WorkThread")

And then an exception was raised not after start of WorkThread but when initializing, so

class UploadDialog(QtGui.QDialog):

    def __init__(self):
        try:
            self.task = WorkThread()
        except Exception:
            self.logger.exception("Exception in WorkThread")

And here I just took my head and screamed to myself - "STOP IT. YOU'RE DOING IT WRONG. It's not pythonic, it's dirty, it makes my eyes bleed".

So, I'm asking - is there any elegant and pythonic way to grab ABSOLUTELY any exception, raised in PyQt app with one try...except block?

解决方案

The point of using an excepthook is so you can monitor all exceptions that are raised by your program, and handle them centrally.

So you should get rid of most of those try/except blocks, and log the exceptions inside the excepthook function. I say "most", because you may be affected by 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中的任何异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆