简体   繁体   English

python 3:使用异步任务时如何在异步 function 中等待回调

[英]python 3 : how to wait for the callback in async function when use asyncio tasks

AWS IoT python Sdk has a function publishAsync AWS IoT python Sdk 有一个 function publishAsync
the signature of the function is publishAsync(topic, payload, QoS, ackCallback=None) function 的签名是 publishAsync(topic, payload, QoS, ackCallback=None)

I want to warp this to a coroutine and use asyncio.我想把它变成一个协程并使用 asyncio。

what I want to do is this:我想做的是:

  1. connect to AWS连接到 AWS
  2. publish 10 messages asynchronously异步发布 10 条消息
  3. disconnect断开

I don't know how should I wrap that function to a async function.我不知道我应该如何将 function 包装成异步 function。

async def asyncPublish(self,
                     msg:str,
                     topic:str,
                     QoS=1):

        # the publishAckFn
        def internalPubAckHandler(mid):
            print(json.dumps({
                'messageID':mid,
                'acknowledged':True
            }))
            return True
        pass

        # publish to the topic asynchronously
        messageID = self.awsIoTClient.publishAsync(topic,msg,QoS,ackCallback=internalPubAckHandler)
        print(json.dumps({
           'messageID':messageID,
           'topic':topic,
           'payload':msg,
           'QoS':QoS,
           'async':True
        }))

    pass


---- in my main file
tasks = []
for i in range(10):
        tasks += asyncPublish('test','test')
pass

loop = asyncio.get_event_loop()
loop.set_debug(True)  # debug mode
gw1.connect()
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
gw1.disconnect()  

but when I do this, the disconnect will be called sooner than internalPubAckHandler and I will not get any acknowledgment.但是当我这样做时,断开连接将比 internalPubAckHandler 更快地调用,我不会得到任何确认。

Finally, I find the solution.最后,我找到了解决方案。 We can use futures.我们可以使用期货。

Future objects are used to bridge low-level callback-based code with high-level async/await code. Future 对象用于将基于回调的低级代码与高级异步/等待代码连接起来。 Ref参考

If the signature of the function is something like this:如果 function 的签名是这样的:

def functionWithCallback(args,callback)

and we need to wrap this to a async function that waits for the callback, we can do something like the following:我们需要将其包装到等待回调的异步 function 中,我们可以执行以下操作:

async def asyncVersion(args):

    # one way of creating a future
    loop = asyncio.get_running_loop()
    future = loop.create_future()

    def futureCallback():
        # do something here and then signal the future
        ...
        loop.call_soon_threadsafe(future .set_result,time.time())
    pass

    # call your function
    functionWithCallback(args,futureCallback)

    # wait for the callback
    await future


    # do other stuff after the callback is done
    .....

pass

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM