PyQt wake main thread from non-QThread
<p>I have a PyQt application that receives information from an external source via callbacks that are called from threads that are not under my control and which are not <code>QThread</code>. What is the correct way to pass such information to the main thread, without polling? Particularly, I want to emit a Qt signal such that I can wake the main thread (or another <code>QThread</code>) upon arrival of new data.</p>

<p>The default connection type for signals is <a href="http://doc.qt.io/qt-4.8/qt.html#ConnectionType-enum" rel="nofollow">Qt.AutoConnection</a>, which the docs describe thus:</p>

<blockquote>
  <p>If the signal is emitted from a different thread than the receiving
  object, the signal is queued, behaving as Qt::QueuedConnection.
  Otherwise, the slot is invoked directly, behaving as
  Qt::DirectConnection. The type of connection is determined when the
  signal is emitted.</p>
</blockquote>

<p>So before emitting a signal, Qt simply compares the <strong>current</strong> thread affinity of the sender and receiver before deciding whether to queue it or not. It does not matter <em>how</em> the underlying threads were originally started.</p>

<p>Here is a simple demo using a python worker thread:</p>

<pre><code>import sys, time, threading
from PyQt4 import QtCore, QtGui

class Worker(object):
    def __init__(self, callback):
        self._callback = callback
        self._thread = None

    def active(self):
        return self._thread is not None and self._thread.is_alive()

    def start(self):
        self._thread = threading.Thread(target=self.work, name='Worker')
        self._thread.start()

    def work(self):
        print('work: [%s]' % threading.current_thread().name)
        for x in range(5):
            time.sleep(1)
            self._callback(str(x))

class Window(QtGui.QPushButton):
    dataReceived = QtCore.pyqtSignal(str)

    def __init__(self):
        super(Window, self).__init__('Start')
        self.clicked.connect(self.start)
        self.dataReceived.connect(self.receive)
        self.worker = Worker(self.callback)

    def receive(self, data):
        print('received: %s [%s]' % (data, threading.current_thread().name))

    def callback(self, data):
        print('callback: %s [%s]' % (data, threading.current_thread().name))
        self.dataReceived.emit(data)

    def start(self):
        if self.worker.active():
            print('still active...')
        else:
            print('start: [%s]' % threading.current_thread().name)
            self.worker.start()

if __name__ == '__main__':

    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.show()
    print('show: [%s]' % threading.current_thread().name)
    sys.exit(app.exec_())
</code></pre>

<p>Typical output:</p>

<pre><code>$ python test.py
show: [MainThread]
start: [MainThread]
work: [Worker]
callback: 0 [Worker]
received: 0 [MainThread]
still active...
callback: 1 [Worker]
received: 1 [MainThread]
still active...
callback: 2 [Worker]
received: 2 [MainThread]
still active...
callback: 3 [Worker]
received: 3 [MainThread]
callback: 4 [Worker]
received: 4 [MainThread]
</code></pre>

python multithreading qt pyqt qthread