如何等待另一个协程?

How to await on another co-routine?

这是我想做的事情:

req.seq = 123
result = await client.sendReq(req)
doResult(result)

够简单吧?然而,在这种情况下,客户端委托给一个 websocket,该 websocket 在一个套接字上处理多个异步请求——它接收到的消息是为等待请求响应的许多协程之一准备的。

这对于实施 client.sentReq 意味着什么?类似于:

换句话说,client.sentReq一定是一个正在等待另一个协程的future。 如何才能做到这一点?对于每一个包含新线程的答案,一个仙女都会死去。

在实践中,我现在拥有的是:

async def doResult(result): ....

req.seq = 123
result = await client.sendReq(req, doResult)

这显然不太好,特别是在异常处理方面。

可以使用Condition, more less:

class Handler:
   def __init__(self):
      self.condition = asyncio.Condition()
      self.response = None

   async def dispatch(self, msg):
       self.response = msg
       async with self.condition:
          msg.notify_all()
    
   async def awaitResponse(self):
       async with self.condition:
           self.condition.wait()
       return self.response
    
async def listener():
   while True:
        msg = await readSocket()
        handler = handler[msg.seq]
        del handler[msg.seq]
        loop.create_task(handler.dispatch(msg))

async def sendReqAwaitResponse(req):
    req.seq = nextSeq()
    handler = Handler()
    seq2Handler[req.seq] = handler
    await _send(req)
    return handler.awaitResponse()
    

async def thing()
   req.seq = 123
   result = await sendReqAwaitResponse(req)
   doResult(result)

async def main():
   # Connect to socket run listener
   # thing() called some time later.


seq2Handler = {}
loop = asyncio.get_event_loop()

if __name__=='__main__':
   loop.run_until_complete(main())

Python <3.10 中的条件存在一些错误。请参阅此处了解解决方法。 How can I use asyncio.Condition within a Task in Python < v3.10