Domanda

I have problems with not getting (printing) error informations from QThread. I have a Worker (QThread):

class Worker(QThread):
    def __init__(self, parent=None):
        QThread.__init__(self, parent)

    def run(self):
        #   do some heavy work here
        print 1     #   1 is printed in my OutputWidget
        print a     #   a is not defined and it should print an error

If I run only the last line (print a) in new file (where a is not defined) I get an error (which is correct and expected):

Traceback (most recent call last):
  File "C:\...\output_widget\output_from_qthread_V2.py", line 1, in run
    print a
NameError: global name 'a' is not defined

OutputWidget:

import sys
from PyQt4 import QtGui
from PyQt4 import QtCore

from output_widget_ui import Ui_Form

class TextOutputSignal(QtCore.QObject):
    textWritten = QtCore.pyqtSignal(str)
    def write(self, text):
        self.textWritten.emit(str(text))

class OutputWidget(QtGui.QWidget):

    def __init__(self, parent=None, flags=0):
        super(OutputWidget, self).__init__(parent)
        sys.stdout = TextOutputSignal(textWritten=self.normalOutputWritten)

        self.ui = Ui_Form()
        self.ui.setupUi(self)

    def __del__(self):
        #    Restore sys.stdout
        sys.stdout = sys.__stdout__

    def normalOutputWritten(self, text):
        cursor = self.ui.textOutputWidget.textCursor()
        cursor.movePosition(QtGui.QTextCursor.End)
        cursor.insertText(text)
        self.ui.textOutputWidget.ensureCursorVisible()

I would like to know why the error is not printed in OutputWidget nor in console (using eclipse)? How can I solve the problem?

È stato utile?

Soluzione

You first need a catch-all exception clause in your thread, otherwise your exception (from a being non-existent global) will go uncaught and cause thread and app exit. Then, from that catch-all, you call sys.exc_info() to get traceback info and sys.excepthook() with the traceback info. This will send traceback to stderr (rather than stdout). So try for OutputWidget:

def __init__(...):
    ...
    sys.stdout = TextOutputSignal(textWritten=self.normalOutputWritten)
    sys.stderr = TextOutputSignal(textWritten=self.errorOutputWritten)
    ...

def errorOutputWritten(self, text):
    self.normalOutputWritten("*** ERROR: " + text)

and for your worker thread:

class Worker(QThread):
    ...

    def run(self):
        try: 
            #   do some heavy work here
            print 1     #   1 is printed in my OutputWidget
            print a     #   a is not defined and it should print an error
        except: 
            (type, value, traceback) = sys.exc_info()
            sys.excepthook(type, value, traceback)
            ...decide if should exit thread or what...

In the above, the exception will cause thread to exit gracefully and you will see an error in console. In general, you will want to signal the main thread some error status too so that the application can determine what to do: show the user an error that network connectivity was lost, etc, and app must decide if it should exit, save work, whatever.

Note that if you have a couple specific exceptions that you want to deal with directly, like division by 0 or NameError, you trap directly, and keep the catch-all for truely exceptional conditions (unexpected exceptions):

    def run(self):
        try: 
            #   do some heavy work here
            print 1     #   1 is printed in my OutputWidget
            print a     #   a is not defined and it should print an error
        except NameError, exc: 
            sys.stderr.write( "Name Error\n" );
            ...decide if should exit thread or what...
        except: 
            (type, value, traceback) = sys.exc_info()
            sys.excepthook(type, value, traceback)
            ...decide if should exit thread or what...
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top