[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