PyPubSub's sendMessage() will call listeners in the same thread as the sender (default Python behavior). In a multithreaded GUI app, you must ensure that listeners that interact with GUI are called in the main thread. Also threads execute independently, so you need each thread to call its own listeners, based on a timed or idle callback mechanism.
The way to call listeners in the correct thread in PyQt is via signals. PyPubSub can still be used in a multithreaded PyQt GUI, but the mechanism used to transfer the "message" from sender to listener would have to be via a signal. There isn't one best way to do it I don't think, depends on details of your app design. You could for example have a QtPubsubHandler
that derives from QObject
and gets created in main thread, and a QtPubsubSender
class that also derives from QObject
and gets created in each worker thread. The QtPubSubSender
defines a custom signal, say pubsub
, which QtPubsubHandler
connects to. Then to send a message, the sender does qtPubsubHandler.sendMessage(topic, **data)
, which causes a pubsub
signal to get emitted, which Qt properly queues and eventually signals the QtPubsubHandler
, which actually calls pub.sendMessage()
.
There are many other ways, but you get the general idea: two classes that derive from QObject, and one of them does the actual sending in the same thread as the intended listener, the other uses a signal so everything is thread safe. Actually you don't have to use PyQt signals: but then you would have to have a queue in main thread and have an idle callback that allows it to process any items on the queue.