PyQt crashing out as a Windows APPCRASH

pyqt, python

Solution

Ok, one thing first about the thread safety of your program. Because you are connecting a `QObject` to stdout, calls to `print` will interact with this `QObject`. But you should only interact with a `QObject` from the thread it was created in. The implementation you have is potentially thread unsafe if you call `print` from a thread other than the one the `QObject` resides in.

In your case, you are calling `print` from a `QThread` while the `EmmittingStream(QObject)` resides in the main thread. I suggest you thus change your code to make it threadsafe, like so:

self.myLongTask = TaskThread()
sys.stdout = EmittingStream(textWritten=self.normalOutputWritten)
sys.stdout.moveToThread(self.myLongTask)
self.myLongTask.start()

Note that now calling `print` from the MainThread of your application will result in thread-unsafe behaviour. Since you aren't doing that at the moment, you are OK for now, but be warned!

I really suggest you read http://qt-project.org/doc/qt-4.8/threads-qobject.html and get your head around everything it talks about. Understanding that document is the key to avoiding annoying crashes due to threads.

--

Now, The issue with the crash is apparently caused by your call to `processEvents()`. I haven't worked out why (I imagine it is related to threads somehow...), but I can tell you that you do not need that line! Because you are using signals/slots, once the `normalOutputWritten` method runs, control returns to the Qt Event Loop anyway, and it will continue to process events as normal. There is thus no need to force Qt to process events!

Hope that helps!

EDIT: For an example of how to make your `EmittingStream`/`print` calls thread-safe, see here: Redirecting stdout and stderr to a PyQt4 QTextEdit from a secondary thread

Problem

I have a very short PyQt program (n.b. that is a PythonFiddle link - this seems to crash horribly in Firefox, so code is also posted below) which prints output to a `QTextEdit` (using code from this SO answer). When I run the code (on Windows), it results in an APPCRASH. Some observations: - if I add a `time.sleep` call (i.e. uncomment out line 53), then the program completes fine - if I don’t redirect the output to the QEdit (i.e. comment out line 34) then it works regardless of whether the `time.sleep` call is commented out or not I assume that this implies that the code redirecting the `stdout` is broken somehow - but I'm struggling to understand what's wrong with it to result in this behaviour - any pointers gratefully received! Full error message Problem signature: Problem Event Name: APPCRASH Application Name: pythonw.exe Application Version: 0.0.0.0 Application Timestamp: 5193f3be Fault Module Name: QtGui4.dll Fault Module Version: 4.8.5.0 Fault Module Timestamp: 52133a81 Exception Code: c00000fd Exception Offset: 00000000005cbdb7 OS Version: 6.1.7601.2.1.0.256.48 Locale ID: 2057 Additional Information 1: 5c9c Additional Information 2: 5c9c27bb85eb40149b414993f172d16f Additional Information 3: bc7e Additional Information 4: bc7e721eaea1ec56417325adaec101aa Pythonfiddle crashes horribly on Firefox (for me at least), so code below too: ``` import os, sys, time, calendar, math from PyQt4 import QtCore, QtGui class EmittingStream(QtCore.QObject): textWritten = QtCore.pyqtSignal(str) def write(self, text): self.textWritten.emit(str(text)) class myWrapper(QtGui.QMainWindow): def __init__(self): super(myWrapper, self).__init__() self.toolbar = self.addToolBar("MainMenu") self.toolbar.addAction(QtGui.QAction("myProg", self, triggered=self.myProgActions)) def myProgActions(self): self.setCentralWidget(myWidget()) class myWidget(QtGui.QWidget): def __init__(self): super(myWidget, self).__init__() self.myBtn = QtGui.QPushButton('Run!', self) self.myBtn.clicked.connect(self.startTest) self.outputViewer = QtGui.QTextEdit() self.grid = QtGui.QGridLayout() self.grid.addWidget(self.myBtn) self.grid.addWidget(self.outputViewer) self.setLayout(self.grid) def startTest(self): self.myLongTask = TaskThread() sys.stdout = EmittingStream(textWritten=self.normalOutputWritten) self.myLongTask.start() def normalOutputWritten(self, text): cursor = self.outputViewer.textCursor() cursor.movePosition(QtGui.QTextCursor.End) cursor.insertText(text) self.outputViewer.setTextCursor(cursor) self.outputViewer.ensureCursorVisible() QtGui.qApp.processEvents() class TaskThread(QtCore.QThread): def __init__(self): super(TaskThread, self).__init__() def run(self): myProgClass() class myProgClass: def __init__(self): for i in range(0,100): print "thread", i+1, " ", math.sqrt(i) #time.sleep(0.005) if __name__ == '__main__': app = QtGui.QApplication(sys.argv) myApp = myWrapper() myApp.show() sys.exit(app.exec_()) ```

Original source

Related problems