I have a threaded application where I do have a network thread. The UI-part passes a callback
to this thread. The thread is a normal python thread - it's NO QThread
.
Is it possible to emit PyQT Slot within this thread?
Emit is a Python library for realtime data processing. It can distribute work with Celery or RQ, coordinate execution in other languages, and let you swing from the trees of your graph with Tarzan-like precision.
The Python standard library provides threading , which contains most of the primitives you'll see in this article. Thread , in this module, nicely encapsulates threads, providing a clean interface to work with them. When you create a Thread , you pass it a function and a list containing the arguments to that function.
The threading is efficient in CPython, but threads can not run concurrently on different processors/cores. This is probably what was meant. It only affects you if you need to do shared memory concurrency. Other Python implementations does not have this problem.
No, it is not possible to emit a PyQt signal from a python thread like this.
However, a possible solution is to use an additional object shared by both threads, making the necessary operations to finally emit a thread-safe PyQt signal.
Here is an implementation of a "SafeConnector" class, making use of a pair of connected sockets and a Queue to exchange data between the two threads, and using a QSocketNotifier to get back in Qt's loop. A QObject is used to make it possible to emit a proper Qt signal:
from PyQt4 import Qt, QtCore, QtGui
import threading
import socket
import Queue
import time
# Object of this class has to be shared between
# the two threads (Python and Qt one).
# Qt thread calls 'connect',
# Python thread calls 'emit'.
# The slot corresponding to the emitted signal
# will be called in Qt's thread.
class SafeConnector:
def __init__(self):
self._rsock, self._wsock = socket.socketpair()
self._queue = Queue.Queue()
self._qt_object = QtCore.QObject()
self._notifier = QtCore.QSocketNotifier(self._rsock.fileno(),
QtCore.QSocketNotifier.Read)
self._notifier.activated.connect(self._recv)
def connect(self, signal, receiver):
QtCore.QObject.connect(self._qt_object, signal, receiver)
# should be called by Python thread
def emit(self, signal, args):
self._queue.put((signal, args))
self._wsock.send('!')
# happens in Qt's main thread
def _recv(self):
self._rsock.recv(1)
signal, args = self._queue.get()
self._qt_object.emit(signal, args)
class PythonThread(threading.Thread):
def __init__(self, connector, *args, **kwargs):
threading.Thread.__init__(self, *args, **kwargs)
self.connector = connector
self.daemon = True
def emit_signal(self):
self.connector.emit(QtCore.SIGNAL("test"), str(time.time()))
def run(self):
while True:
time.sleep(1)
self.emit_signal()
if __name__ == '__main__':
app = QtGui.QApplication([])
mainwin = QtGui.QMainWindow()
label = QtGui.QLabel(mainwin)
mainwin.setCentralWidget(label)
connector = SafeConnector()
python_thread = PythonThread(connector)
connector.connect(QtCore.SIGNAL("test"), label.setText)
python_thread.start()
mainwin.show()
app.exec_()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With