<!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>