如何等待另一个协程?
How to await on another co-routine?
这是我想做的事情:
req.seq = 123
result = await client.sendReq(req)
doResult(result)
够简单吧?然而,在这种情况下,客户端委托给一个 websocket,该 websocket 在一个套接字上处理多个异步请求——它接收到的消息是为等待请求响应的许多协程之一准备的。
这对于实施 client.sentReq
意味着什么?类似于:
- client.sentReq 必须做到:
socket.awaitSend(req)
- 处理程序已在某处注册:
seq2handler[req.seq] = handler
- 在另一个协程中 client.recvReq 最终收到响应,查找
seq2handler[response.seq](response)
并导致 client.sendReq
到 return 收到的响应。
换句话说,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
这是我想做的事情:
req.seq = 123
result = await client.sendReq(req)
doResult(result)
够简单吧?然而,在这种情况下,客户端委托给一个 websocket,该 websocket 在一个套接字上处理多个异步请求——它接收到的消息是为等待请求响应的许多协程之一准备的。
这对于实施 client.sentReq
意味着什么?类似于:
- client.sentReq 必须做到:
socket.awaitSend(req)
- 处理程序已在某处注册:
seq2handler[req.seq] = handler
- 在另一个协程中 client.recvReq 最终收到响应,查找
seq2handler[response.seq](response)
并导致client.sendReq
到 return 收到的响应。
换句话说,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