Setup
I am working on an application using Qt and Python with threads and experiance occational core dumps. I stripped down my code to a minimum working example and would like to know, what might be causing the core dumps. My application has the following goals:
- I need to handle a compuational expensive task in a separat thread. I am using the python threading module for the thread creation.
- The logging that occurs in that thread should be visualized in the GUI
- The thread should send data to the GUI that should also be visualized
My setup is as follows:
Logging
I created a new logging handler that is attached to the logger and sends the log message via a queue to the main thread:
class TextEditHandler(logging.Handler):
def __init__(self, queue):
super(TextEditHandler, self).__init__(logging.INFO)
self.queue = queue
def emit(self, record):
self.queue.put(self.format(record))
GUI
I am using a QDialog for the GUI that is created from the main window of my application. The QDialog has the following tasks:
- It holds the QTextEdit which displays the log messages and data
- It creates the log queue and attaches the
TextEditHandler
to the logger and passes the log queue to theTextEditHandler
- It creates a QTimer that triggers in a fixed intervall and checks the log queue as well as the thread queue for new log messages/data.
- It creates the thread as well as a thread queue in which the data is sent from the thread.
In code terms it looks like this:
class Dialog(QtGui.QDialog):
def __init__(self):
super(Dialog, self).__init__()
self.logWidget = QtGui.QTextEdit()
self.logWidget.setReadOnly(True)
layout = QtGui.QHBoxLayout()
layout.addWidget(self.logWidget)
self.setLayout(layout)
self.loggingQueue = Queue.Queue()
self.loggingHandler = TextEditHandler(self.loggingQueue)
logging.getLogger().addHandler(self.loggingHandler)
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.TimerCallback)
self.timer.start(1)
self.threadQueue = Queue.Queue()
self.thread = threading.Thread(target=self.ThreadCallback, args=(self.threadQueue,))
self.thread.daemon = True
self.thread.start()
Thread
For completeness the thread in this minimum working example looks like this:
@classmethod
def ThreadCallback(cls, queue):
for i in range(1000):
time.sleep(0.001)
logging.info("Log message {}".format(i))
queue.put(i ** 2)
Timer
The timer call back methods should do the following:
- It should check the logging queue for new log messages and pass them to the QTextEdit widget.
- Also the thread queue should be checked and received data handled
In order for the timer to not block I need to check the queues non blocking (queue.get(False)
). In code terms it looks like this:
def TimerCallback(self):
try:
log = self.loggingQueue.get(False)
self.logWidget.append(log)
cursor = self.logWidget.textCursor()
cursor.movePosition(QtGui.QTextCursor.End)
self.logWidget.setTextCursor(cursor)
except Queue.Empty:
pass
try:
data = self.threadQueue.get(False)
print("Data: {}".format(data))
except Queue.Empty:
return
Missing Code for MWE
import logging
from PySide import QtCore, QtGui
import Queue
import threading
import time
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
app = QtGui.QApplication(["test"])
dialog = Dialog()
dialog.show()
app.exec_()
Questions
Round about every 10-15 times a core dump occures and I have a feeling it has something to do with my threading implementation. I am fairly new to multi threaded programming and would appreciate any hint, help or suggestion you might have. I also gave the QThread class a try but found the python threads easier to comprehend.
Miscellaneous
- Python version: 2.7.14
- PySide version: 1.2.4
- The code is run in a normal console, if it is run from inside the IDE (PyCharm) the problem is not reproducable.
Edit
I switched to PyQt4 as three_pineapples suggested and the core dumps appear to be fixed.