вернуть данные on_message в python paho mqtt

Я реализую клиент paho mqtt. Вот мой код:

import paho.mqtt.client as mqtt


def mess(client, userdata, message):
   print("{'" + str(message.payload) + "', " + str(message.topic) + "}")


def subscribe(c_id, topic, server, port):
   cl = mqtt.Client(c_id)
   cl.connect(server, port)
   cl.subscribe(topic)
   cl.on_message = mess
   cl.loop_forever()

это отлично работает, но я не хочу печатать данные в «беспорядке». Мне нужно вернуть строку внутри print() вызывающей функции. Я звоню subscribe() из другой программы. Будем признательны за любую помощь, прямое или рекомендуемое чтение.


person Viraj Jagale    schedule 18.06.2016    source источник


Ответы (3)


С тем, что вы показали, вам нужно использовать флаг global для обновления переменной data вне функции.

data = ''

def mess(client, userdata, message):
  global data
  data = "{'" + str(message.payload) + "', " + str(message.topic) + "}"

Кроме того, функция subscribe никогда не вернется как есть, потому что она вызывает cl.loop_forever(). Если вы хотите, чтобы он вернулся, вы должны позвонить cl.loop_start()

Печать data в subscribe также не будет работать, потому что клиент не может фактически обработать входящее сообщение, пока вы не запустите сетевой цикл (строка после его печати).

Также нет гарантии, когда сообщение будет доставлено после подписки на тему.

Не зная намного больше о том, чего именно вы пытаетесь достичь, я не могу больше помочь, но я думаю, что вам нужно вернуться и посмотреть на весь ваш подход, чтобы принять асинхронный характер обмена сообщениями pub/sub.

person hardillb    schedule 18.06.2016
comment
я пытался напечатать/вернуть глобальную переменную после on_message, но это ничего не делает, я думаю, потому что on_message не блокирует. Оператор print/return выполняется до получения любого сообщения. Есть ли способ через это? - person Viraj Jagale; 18.06.2016
comment
Отредактируйте свой исходный вопрос, указав ВСЕ код, который у вас есть в настоящее время, то, что вы описали, не соответствует коду, который вы показали. - person hardillb; 18.06.2016

У меня был точно такой же вопрос, и ответ от hardillb помог. Я просто хочу привести полный пример с использованием loop_start() и loop_stop().

import paho.mqtt.client as mqtt
import time

current_pose = -1
def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))
    print("The position will will be printed in [mm]")
    client.subscribe("send position",qos=1)

def on_message(client, userdata, msg):
    global current_pose
    current_pose = msg.payload.decode('utf8')
    print("Position = ",current_pose)

client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect("localhost", 1883, 60)
client.loop_start()

for i in range(0,10):
    time.sleep(1) # wait 1s
    print('current_pose = ', current_pose)
    
client.loop_stop() 
print('the position will not be updated anymore') 

в этом примере позиция печатается каждую секунду в течение десяти секунд, дополнительно данные будут выведены обратным вызовом on_message.

person JDArango    schedule 04.02.2021

Вместо упомянутого метода глобальных переменных также можно использовать пакет Queue.

import Queue
import paho.mqtt.client as mqtt

q = Queue.Queue() #initialises a first in first out queue

def mess(client, userdata, message):
    q.put(("{'" + str(message.payload) + "', " + str(message.topic) + "}"))

if not q.empty(): #check if the queue is empty
    msg = q.get()  #get the first message which was received and delete

Это позволяет избежать потери каких-либо входящих данных или любого повреждения данных, к которым осуществляется доступ, которые перезаписываются во время использования.

person bigglet    schedule 06.03.2018
comment
Я считаю, что этот подход имеет ту же проблему, что и исходный вопрос. В частности, вам нужно найти способ включить очередь в область действия функции беспорядка. Вам нужно будет сделать глобальную очередь, чтобы получить к ней доступ вне функции, чтобы вызвать Q.get(). - person Nick Settje; 31.08.2018
comment
@Nick Вы всегда можете использовать functools.partial, чтобы позаботиться об этом: def mess(Q, ...): ... client.on_message = functools.partial(mess, Q) - person David Jablonski; 26.02.2019