[PyQt] Uncaught exceptions
slepton at posteo.de
slepton at posteo.de
Sun Feb 16 14:24:58 GMT 2020
Hello,
in the past I had some trouble with uncaught exception (e.g. PyCharm
does not show the traceback, at least not without further adjustments,
without console output the information is lost, ...). There are many
posts on Stackoverflow and else where, based on
timlehr.com/python-exception-hooks-with-qt-message-box/ [1]and
fman.io/blog/pyqt-excepthook/ [2]the solution below suits all my needs
and might be be usefull to others.
Cheers
Sebastian
import logging
import sys
import traceback
import datetime
from PyQt5.QtCore import QObject
from PyQt5.QtWidgets import QApplication, QMessageBox
from collections import namedtuple
fake_tb = namedtuple('fake_tb', ('tb_frame', 'tb_lasti', 'tb_lineno',
'tb_next'))
class UncaughtHook(QObject):
"""Show exceptions in a QMessageBox and add missing frames to the trace
Usage example:
--------------
import sys
from PyQt5.QtWidgets import QApplication
uncaught_hook_handler = UncaughtHook()
# Setting the hook first, import errors (e.g. missing modules)
# will be caught and shown graphically as well
sys.excepthook = uncaught_hook_handler.exception_hook
app = QApplication([])
if __name__ == '__main__':
form your_application import Window
window = Window()
window.show()
app.exec()
This is based on Exception handling code with popups by Tim Lehr
http://timlehr.com/python-exception-hooks-with-qt-message-box/
and "adding missing frames" by Michael Herrmann
https://fman.io/blog/pyqt-excepthook/
please see original posts for details and examples.
"""
def __init__(self, *args, **kwargs):
super(UncaughtHook, self).__init__(*args, **kwargs)
self.log = logging.getLogger(__name__)
self.handler = logging.StreamHandler(stream=sys.stdout)
self.log.addHandler(self.handler)
def exception_hook(self, exc_type, exc_value, exc_traceback):
"""Custom except hook, showing a QMessageBox if possible."""
exc_traceback = self._add_missing_frames(exc_traceback) if
exc_traceback else exc_traceback
# Allow debugging of non-gui applications
if not issubclass(exc_type, KeyboardInterrupt) and
QApplication.instance() is not None:
log_msg = 'n'.join([''.join(traceback.format_tb(exc_traceback)),
'{0}: {1}'.format(exc_type.__name__, exc_value)])
# Uncomment lines below when logging to a file is enabled
# exc_info = (exc_type, exc_value, exc_traceback)
# self.log.critical("Uncaught exception:n {0}".format(log_msg),
exc_info=exc_info)
reply = QMessageBox.critical(None, 'Uncaught Exception, closing
application ...',
str(log_msg), QMessageBox.Save | QMessageBox.No)
# Comment lines below when logging to a file is enabled
# Otherwise the user can save a crash report
if reply == QMessageBox.Save:
log_file =
datetime.datetime.now().strftime('Crash_report-%Y-%m-%d_%H-%M-%S.log')
with open(log_file, 'w') as fh:
fh.write(log_msg)
print('SAVED CRASH REPORT TO', Path(log_file).absolute())
traceback.print_exception(exc_type, exc_value, exc_traceback)
sys.exit(-1)
@staticmethod
def _add_missing_frames(tb):
result = fake_tb(tb.tb_frame, tb.tb_lasti, tb.tb_lineno, tb.tb_next)
frame = tb.tb_frame.f_back
while frame:
result = fake_tb(frame, frame.f_lasti, frame.f_lineno, result)
frame = frame.f_back
return result
Links:
------
[1] http://timlehr.com/python-exception-hooks-with-qt-message-box/%20
[2] https://fman.io/blog/pyqt-excepthook/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20200216/44f388fa/attachment.html>
More information about the PyQt
mailing list