Search code examples
pythonpyqt5amqppyside2pika

How to integrate Pika with Qt?


Recently, a user asked how to use Pika with Qt, but unexpectedly the user deleted when I was about to post my answer, which gave me the opportunity to propose this question with an auto-answer where I try to expose various solutions:


Solution

  • Using BlockingConnection the start_consuming() method must be executed in another thread, in addition it must be known that the callbacks are executed in a secondary thread so if you want to update the GUI then signals must be emitted

    import threading
    
    from PyQt5 import QtCore, QtWidgets
    # or
    # from PySide2 import QtCore, QtWidgets
    
    import pika
    
    
    class RabbitMQManager(QtCore.QObject):
        messageChanged = QtCore.pyqtSignal(str)
        # or
        # messageChanged = QtCore.Signal(str)
    
        def __init__(self, *, parameters=None, parent=None):
            super().__init__(parent)
    
            self._connection = pika.BlockingConnection(parameters)
    
        @property
        def connection(self):
            return self._connection
    
        def start(self):
            channel = self.connection.channel()
            channel.queue_declare(queue="hello")
            channel.basic_consume(
                queue="hello", on_message_callback=self._callback, auto_ack=True,
            )
            threading.Thread(target=channel.start_consuming, daemon=True).start()
    
            print(" [*] Waiting for messages. To exit press CTRL+C")
    
        def _callback(self, ch, method, properties, body):
            print(" [x] Received %r" % body)
            self.messageChanged.emit(body.decode())
    
    
    def main():
    
        import signal
        import sys
    
        # https://stackoverflow.com/a/6072360
        signal.signal(signal.SIGINT, signal.SIG_DFL)
    
        app = QtWidgets.QApplication(sys.argv)
    
        w = QtWidgets.QTextEdit()
        w.resize(640, 480)
        w.show()
    
        credentials = pika.PlainCredentials("user", "user")
        parameters = pika.ConnectionParameters("127.0.0.1", 5672, "/", credentials)
    
        rabbit_manager = RabbitMQManager(parameters=parameters)
        rabbit_manager.start()
    
        rabbit_manager.messageChanged.connect(w.append)
    
        sys.exit(app.exec_())
    
    
    if __name__ == "__main__":
        main()