Python 3.x 将paho MQTT与Python中的另一个异步IO进程相结合

Python 3.x 将paho MQTT与Python中的另一个异步IO进程相结合,python-3.x,asynchronous,mqtt,Python 3.x,Asynchronous,Mqtt,我在Python中有一个基本的MQTTListener类,它侦听关于某些主题的消息,并且应该启动或停止从另一个脚本导入的异步进程。除非手动停止,否则此进程将永远运行。让我们假设侦听器如下所示: import paho.mqtt.client as mqtt import json from python_file.py import async_forever_function class MqttListener: def __init__(self, host, port, cl

我在Python中有一个基本的MQTTListener类,它侦听关于某些主题的消息,并且应该启动或停止从另一个脚本导入的异步进程。除非手动停止,否则此进程将永远运行。让我们假设侦听器如下所示:

import paho.mqtt.client as mqtt
import json
from python_file.py import async_forever_function

class MqttListener:

    def __init__(self, host, port, client_id):
        self.host = host
        self.port = port
        self.client_id = client_id
        self.client = mqtt.Client(client_id=self.client_id)
        self.client.connect(host=self.host, port=self.port)

    def on_connect(self, client, userdata, flags, rc):
        self.client.subscribe(topic=[("start", 1), ])
        self.client.subscribe(topic=[("stop", 1), ])
        logging.info(msg="MQTT - connected!")

    def on_disconnect(client, userdata, rc):
        logging.info(msg="MQTT - disconnected!")

    def on_message(self, client, userdata, message, ):
        print('PROCESSING MESSAGE', message.topic, message.payload.decode('utf-8'), )

        if message.topic == 'start':
            async_forever_function(param='start')
            print('process started')
        else:
            async_forever_function(param='stop')
            print('process removed')

    def start(self):
        self.client.on_connect = lambda client, userdata, flags, rc: self.on_connect(client, userdata, flags, rc)
        self.client.on_message = lambda client, userdata, message: self.on_message(client, userdata, message)
        self.client.on_disconnect = lambda client, userdata, rc: self.on_disconnect(client, userdata, rc)

        self.client.loop_start()

    def stop(self):
        self.client.loop_stop()
现在,这适用于启动新的异步进程。也就是说,在开始MQTT主题上发布消息时,会正确触发async_函数。但是,一旦启动此异步进程,侦听器将无法再接收/处理来自stop MQTT主题的消息,并且异步进程将永远继续运行,而实际上它本应停止


我的问题:如何调整此类的代码,使其在后台运行活动异步进程时也能处理消息?

您不能在
on_message()
回调中执行阻止任务

此回调在MQTT客户端线程(由
loop\u start()
函数启动的线程)上运行。此线程处理所有网络流量和消息处理,如果您阻止它,则它无法执行任何操作


如果要从
on_message()
回调调用长时间运行的任务,则需要为长时间运行的任务启动一个新线程,这样它就不会阻塞MQTT客户机循环。

您不能在
on_message()
回调中执行阻塞任务

此回调在MQTT客户端线程(由
loop\u start()
函数启动的线程)上运行。此线程处理所有网络流量和消息处理,如果您阻止它,则它无法执行任何操作


如果要从消息()上的
调用长时间运行的任务
callback您需要为长时间运行的任务启动一个新线程,这样它就不会阻塞MQTT客户机循环。

启动消息到达时,
进程是否已启动
打印?编辑问题以显示输出,这样我们就可以看到发生了什么logged@hardillb很抱歉,我误读了您的评论。不,启动的流程未打印,因为async进程仍在运行。当启动消息到达时,
进程已启动
是否已打印?编辑问题以显示输出,以便我们可以查看发生了什么logged@hardillb很抱歉,我误读了您的评论。不,没有打印启动的进程,因为异步进程仍在运行。我尝试通过添加另一个循环来实现您的建议,但我得到RuntimeError:无法在另一个循环运行时运行事件循环。我已尝试解决此问题,但无法解决此问题。您是否可以使用我的通用代码编辑您的答案,以显示启动新线程的含义?不,您不能运行“另一个”循环,您必须在自己的线程上运行
async\u forever\u函数
。那么,解决方案是什么呢?@MarcoLettieri与之前一样。启动一个新线程来运行阻塞/长时间运行任务。我尝试通过添加另一个循环来实现您的建议,但我得到RuntimeError:在另一个循环运行时无法运行事件循环ng.我试图解决这个问题,但无法解决。您可以用我的通用代码编辑您的答案,以显示启动新线程的含义吗?不,您不能运行“另一个”循环,您必须在自己的线程上运行
async\u forever\u函数
。那么,解决方案是什么呢?@MarcoLettieri与之前一样。启动一个新线程以在其上运行阻塞/长时间运行任务。