[prev in list] [next in list] [prev in thread] [next in thread]
List: pykde
Subject: [PyQt] Uncaught exceptions
From: slepton () posteo ! de
Date: 2020-02-16 14:24:58
Message-ID: 964d5ff3f0714d6cd58051a2d16bb702 () posteo ! de
[Download RAW message or body]
[Attachment #2 (multipart/alternative)]
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/
[Attachment #5 (unknown)]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN">
<html><body style='font-size: 10pt; font-family: Verdana,Geneva,sans-serif'>
Hello,<br /><br />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 <a \
title="http://timlehr.com/python-exception-hooks-with-qt-message-box/ " \
href="http://timlehr.com/python-exception-hooks-with-qt-message-box/%20">timlehr.com/python-exception-hooks-with-qt-message-box/ \
</a>and <a title="https://fman.io/blog/pyqt-excepthook/" \
href="https://fman.io/blog/pyqt-excepthook/">fman.io/blog/pyqt-excepthook/ </a>the \
solution below suits all my needs and might be be usefull to others. <br /><br \
/>Cheers <br /><br />Sebastian<br /><br /><br /> <pre style="background-color: \
#2b2b2b; color: #a9b7c6; font-family: 'Consolas'; font-size: 9,8pt;"><span \
style="color: #cc7832;">import </span>logging<br /><span style="color: \
#cc7832;">import </span>sys<br /><span style="color: #cc7832;">import \
</span>traceback<br /><span style="color: #cc7832;">import </span>datetime<br /><br \
/><span style="color: #cc7832;">from </span>PyQt5.QtCore <span style="color: \
#cc7832;">import </span>QObject<br /><span style="color: #cc7832;">from \
</span>PyQt5.QtWidgets <span style="color: #cc7832;">import </span>QApplication<span \
style="color: #cc7832;">, </span>QMessageBox<br /><br /><span style="color: \
#cc7832;">from </span>collections <span style="color: #cc7832;">import \
</span>namedtuple<br /><br />fake_tb = namedtuple(<span style="color: \
#6a8759;">'fake_tb'</span><span style="color: #cc7832;">, </span>(<span style="color: \
#6a8759;">'tb_frame'</span><span style="color: #cc7832;">, </span><span style="color: \
#6a8759;">'tb_lasti'</span><span style="color: #cc7832;">, </span><span style="color: \
#6a8759;">'tb_lineno'</span><span style="color: #cc7832;">, </span><span \
style="color: #6a8759;">'tb_next'</span>))<br /><br /><br /><span style="color: \
#cc7832;">class </span>UncaughtHook(QObject):<br /> <span style="color: #629755; \
font-style: italic;">"""Show exceptions in a QMessageBox and add missing frames to \
the trace<br /></span><span style="color: #629755; font-style: italic;"> <br \
/></span><span style="color: #629755; font-style: italic;"> Usage example:<br \
/></span><span style="color: #629755; font-style: italic;"> --------------<br \
/></span><span style="color: #629755; font-style: italic;"> import sys<br \
/></span><span style="color: #629755; font-style: italic;"> from PyQt5.QtWidgets \
import QApplication<br /></span><span style="color: #629755; font-style: italic;"> \
uncaught_hook_handler = UncaughtHook() <br /></span><span style="color: #629755; \
font-style: italic;"> # Setting the hook first, import errors (e.g. missing \
modules) <br /></span><span style="color: #629755; font-style: italic;"> # will be \
caught and shown graphically as well<br /></span><span style="color: #629755; \
font-style: italic;"> sys.excepthook = uncaught_hook_handler.exception_hook<br \
/></span><span style="color: #629755; font-style: italic;"><br /></span><span \
style="color: #629755; font-style: italic;"> app = QApplication([])<br \
/></span><span style="color: #629755; font-style: italic;"> if __name__ == \
'__main__':<br /></span><span style="color: #629755; font-style: italic;"> \
form your_application import Window<br /></span><span style="color: #629755; \
font-style: italic;"> window = Window()<br /></span><span style="color: \
#629755; font-style: italic;"> window.show()<br /></span><span style="color: \
#629755; font-style: italic;"> app.exec()<br /></span><span style="color: \
#629755; font-style: italic;"> <br /></span><span style="color: #629755; \
font-style: italic;"> This is based on Exception handling code with popups by Tim \
Lehr<br /></span><span style="color: #629755; font-style: italic;"> \
http://timlehr.com/python-exception-hooks-with-qt-message-box/<br /></span><span \
style="color: #629755; font-style: italic;"> and "adding missing frames" by \
Michael Herrmann<br /></span><span style="color: #629755; font-style: italic;"> \
https://fman.io/blog/pyqt-excepthook/<br /></span><span style="color: #629755; \
font-style: italic;"> please see original posts for details and examples.<br \
/></span><span style="color: #629755; font-style: italic;"> """<br /></span><span \
style="color: #629755; font-style: italic;"><br /></span><span style="color: #629755; \
font-style: italic;"> </span><span style="color: #cc7832;">def </span><span \
style="color: #b200b2;">__init__</span>(<span style="color: \
#94558d;">self</span><span style="color: #cc7832;">, </span>*args<span style="color: \
#cc7832;">, </span>**kwargs):<br /> <span style="color: \
#8888c6;">super</span>(UncaughtHook<span style="color: #cc7832;">, </span><span \
style="color: #94558d;">self</span>).<span style="color: \
#b200b2;">__init__</span>(*args<span style="color: #cc7832;">, </span>**kwargs)<br /> \
<span style="color: #94558d;">self</span>.log = logging.getLogger(__name__)<br /> \
<span style="color: #94558d;">self</span>.handler = logging.StreamHandler(<span \
style="color: #aa4926;">stream</span>=sys.stdout)<br /> <span style="color: \
#94558d;">self</span>.log.addHandler(<span style="color: \
#94558d;">self</span>.handler)<br /><br /> <span style="color: #cc7832;">def \
</span><span style="color: #ffc66d;">exception_hook</span>(<span style="color: \
#94558d;">self</span><span style="color: #cc7832;">, </span>exc_type<span \
style="color: #cc7832;">, </span>exc_value<span style="color: #cc7832;">, \
</span>exc_traceback):<br /> <span style="color: #629755; font-style: \
italic;">"""Custom except hook, showing a QMessageBox if possible."""<br \
/></span><span style="color: #629755; font-style: italic;"> \
</span>exc_traceback = <span style="color: \
#94558d;">self</span>._add_missing_frames(exc_traceback) <span style="color: \
#cc7832;">if </span>exc_traceback <span style="color: #cc7832;">else \
</span>exc_traceback<br /> <span style="color: #808080;"># Allow debugging of \
non-gui applications<br /></span><span style="color: #808080;"> </span><span \
style="color: #cc7832;">if not </span><span style="color: \
#8888c6;">issubclass</span>(exc_type<span style="color: #cc7832;">, </span><span \
style="color: #8888c6;">KeyboardInterrupt</span>) <span style="color: #cc7832;">and \
</span>QApplication.instance() <span style="color: #cc7832;">is not None</span>:<br \
/><br /> log_msg = <span style="color: #6a8759;">'</span><span \
style="color: #cc7832;">\n</span><span style="color: #6a8759;">'</span>.join([<span \
style="color: #6a8759;">''</span>.join(traceback.format_tb(exc_traceback))<span \
style="color: #cc7832;">,<br /></span><span style="color: #cc7832;"> \
</span><span style="color: #6a8759;">'{0}: {1}'</span>.format(exc_type.<span \
style="color: #b200b2;">__name__</span><span style="color: #cc7832;">, \
</span>exc_value)])<br /> <span style="color: #808080;"># Uncomment lines \
below when logging to a file is enabled<br /></span><span style="color: #808080;"> \
# exc_info = (exc_type, exc_value, exc_traceback)<br /></span><span style="color: \
#808080;"> # self.log.critical("Uncaught exception:\n \
{0}".format(log_msg), exc_info=exc_info)<br /></span><span style="color: #808080;"> \
</span>reply = QMessageBox.critical(<span style="color: #cc7832;">None, </span><span \
style="color: #6a8759;">'Uncaught Exception, closing application ...'</span><span \
style="color: #cc7832;">,<br /></span><span style="color: #cc7832;"> \
</span><span style="color: #8888c6;">str</span>(log_msg)<span style="color: \
#cc7832;">, </span>QMessageBox.Save | QMessageBox.No)<br /> <span \
style="color: #808080;"># Comment lines below when logging to a file is enabled<br \
/></span><span style="color: #808080;"> # Otherwise the user can save a \
crash report<br /></span><span style="color: #808080;"> </span><span \
style="color: #cc7832;">if </span>reply == QMessageBox.Save:<br /> \
log_file = datetime.datetime.now().strftime(<span style="color: \
#6a8759;">'Crash_report-%Y-%m-%d_%H-%M-%S.log'</span>)<br /> <span \
style="color: #cc7832;">with </span><span style="color: \
#8888c6;">open</span>(log_file<span style="color: #cc7832;">, </span><span \
style="color: #6a8759;">'w'</span>) <span style="color: #cc7832;">as </span>fh:<br /> \
fh.write(log_msg)<br /> <span style="color: \
#8888c6;">print</span>(<span style="color: #6a8759;">'SAVED CRASH REPORT \
TO'</span><span style="color: #cc7832;">, </span>Path(log_file).absolute())<br /> \
traceback.print_exception(exc_type<span style="color: #cc7832;">, \
</span>exc_value<span style="color: #cc7832;">, </span>exc_traceback)<br /> \
sys.exit(-<span style="color: #6897bb;">1</span>)<br /><br /> <span style="color: \
#bbb529;">@staticmethod<br /></span><span style="color: #bbb529;"> </span><span \
style="color: #cc7832;">def </span><span style="color: \
#ffc66d;">_add_missing_frames</span>(tb):<br /> result = \
fake_tb(tb.tb_frame<span style="color: #cc7832;">, </span>tb.tb_lasti<span \
style="color: #cc7832;">, </span>tb.tb_lineno<span style="color: #cc7832;">, \
</span>tb.tb_next)<br /> frame = tb.tb_frame.f_back<br /> <span \
style="color: #cc7832;">while </span>frame:<br /> result = \
fake_tb(frame<span style="color: #cc7832;">, </span>frame.f_lasti<span style="color: \
#cc7832;">, </span>frame.f_lineno<span style="color: #cc7832;">, </span>result)<br /> \
frame = frame.f_back<br /> <span style="color: #cc7832;">return \
</span>result<br /><br /><br /></pre> </body></html>
[Attachment #6 (text/plain)]
_______________________________________________
PyQt mailing list PyQt@riverbankcomputing.com
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic