Home > Net >  Thread fails to return the value of an asynchronous function / TypeError: 'coroutine' obje
Thread fails to return the value of an asynchronous function / TypeError: 'coroutine' obje

Time:10-21

I need to asynchronously execute a function and then save the return value for it to be returned when I need it.

I have the following code:

class EncodingThread(Thread):
    def __init__(self):
        Thread.__init__(self)
        self.value = None
        self.frame = None
    def setFrame(self,frame):
        self.frame=frame
    def run(self):
        self.value = mqtt.publish_message(self.frame)

thread = EncodingThread()


#some function
def somedef():    
    while True:
        #keep in mind that this function does other stuff that I don't want to be disrupted by this routine, so the routine below should be asynchronous
        thread.setFrame(some_value)
        thread_status = thread.is_alive()
        if not thread.is_alive():
            thread.join()
        if not thread_status:
            results = thread.value
            if results != (1 and None) :
                value = results['request']
                return value

The "mqtt.publish_message" function is an async function (using asyncio). If I don't use it, the codeflow "stops" to execute it, and I don't want this happening.

Also, currently I am getting the "TypeError: 'coroutine' object is not subscriptable" error on the line "value = results['request']"

How do I make this code work as intended, where "mqtt.publish_message" is executed asynchronously and the thread accordingly stores the return value of ""mqtt.publish_message" 's execution?

Thank you

CodePudding user response:

Fixing the asyncio issue is not going to completely fix this code. As soon as you start the EnclosingThread, its run method will execute; at that point, the variable self.frame is None. When you try to set it by calling thread.setFrame(some_value), that will be too late: the call to publish_message has already happened in the other thread, and mqtt is already off and running with wrong argument.

To answer your explicit question, secondary threads do not have a default event loop. It must be created and then set before running any async code in that thread, something like this:

def run(self):
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    self.value = loop.run_until_complete(mqtt.publish_message(self.frame))

I don't know anything about mqtt, so you should check to see if it's threadsafe. It is possible that mqtt must be initialized somehow, and that has to be done in the same thread where it's used. The code may fail because of that.

  • Related