I'm trying to write an app that works in system tray using PyQt5. The code is sometimes raising exceptions, and I need to be able to catch them.
I would expect that when an exception occurs in an app, the main event loop is exited, so catching it like that should work:
try:
application.exec()
except:
do_stuff()
In the following example, when I press the "Raise" button, I only see the traceback, but I never see the error catched!
printed.
from PyQt5 import QtWidgets, QtGui, QtCore
class ErrorApp():
def __init__(self):
# Init QApplication, QWidet and QMenu
self.app = QtWidgets.QApplication([])
self.widget = QtWidgets.QWidget()
self.menu = QtWidgets.QMenu("menu", self.widget)
# Add items to menu
self.menu_action_raise = self.menu.addAction("Raise")
self.menu_action_raise.triggered.connect(self.raise_error)
self.menu_action_exit = self.menu.addAction("Exit")
self.menu_action_exit.triggered.connect(self.app.exit)
# Create the tray app
self.tray = QtWidgets.QSystemTrayIcon(QtGui.QIcon("logo.png"), self.widget)
self.tray.setContextMenu(self.menu)
# Show app
self.tray.show()
def raise_error(self):
assert False
e = ErrorApp()
try:
e.app.exec()
except:
print("error catched!")
There are 2 similar questions, but the answers there don't do what I need to do:
Grab any exception in PyQt: the OP wants to monitor the exceptions, the even loop isn't exited
Preventing PyQt to silence exceptions occurring in slots: the decorator answer simply doesn't work; adding sys.exit(1)
to sys.excepthook
just closes the whole program, without printing error catched!
When an exception is raised, no further statements in the current block of code are executed.
Predefined exceptions are raised implicitly (automatically) by the runtime system. User-defined exceptions must be raised explicitly by RAISE statements. To handle raised exceptions, you write separate routines called exception handlers.
Catching Exceptions in Python In Python, exceptions can be handled using a try statement. The critical operation which can raise an exception is placed inside the try clause. The code that handles the exceptions is written in the except clause.
19.1. Catching exceptions. Whenever a runtime error occurs, it creates an exception object. The program stops running at this point and Python prints out the traceback, which ends with a message describing the exception that occurred.
You must use the exception and, if you want the event loop to end then you must call the quit()
(or exit()
) method.
import sys
import traceback
from PyQt5 import QtWidgets, QtGui, QtCore
class ErrorApp:
# ...
def raise_error(self):
assert False
def excepthook(exc_type, exc_value, exc_tb):
tb = "".join(traceback.format_exception(exc_type, exc_value, exc_tb))
print("error catched!:")
print("error message:\n", tb)
QtWidgets.QApplication.quit()
# or QtWidgets.QApplication.exit(0)
sys.excepthook = excepthook
e = ErrorApp()
ret = e.app.exec_()
print("event loop exited")
sys.exit(ret)
Output:
error catched!:
error message:
Traceback (most recent call last):
File "main.py", line 28, in raise_error
assert False
AssertionError
event loop exited
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With