如何await监听被loop.add_reader绑定的fd的关闭事件?
解决方案
你可以通过asyncio.Future作为通知载体,把回调式的文件描述符监听转为可等待的事件,从而替代run_forever()的使用,完整实现代码如下:
import asyncio myfd = ... # 你的文件描述符,示例中为套接字对象 # 创建Future用于传递fd关闭事件 close_future = asyncio.get_event_loop().create_future() def reader(): try: data = myfd.recv(100) # 套接字返回空字节代表对端已关闭连接 if not data: if not close_future.done(): close_future.set_result(None) # 移除注册的读监听,避免重复触发 asyncio.get_event_loop().remove_reader(myfd) return print("Received:", data.decode()) except Exception as e: # 读过程发生异常也视为连接中断,将异常传入Future if not close_future.done(): close_future.set_exception(e) asyncio.get_event_loop().remove_reader(myfd) async def main(): loop = asyncio.get_running_loop() loop.add_reader(myfd, reader) # 等待fd关闭事件触发 await close_future # 此处可添加自定义的善后逻辑 print("myfd已关闭,运行结束") if __name__ == "__main__": asyncio.run(main())
核心逻辑说明
Future是asyncio原生支持的可等待对象,我们用它作为回调函数和协程逻辑之间的通信桥:当回调检测到fd关闭时,就将Future标记为完成状态,await该Future的协程就会继续执行。- 替换原有
run_forever()的无限运行逻辑:使用asyncio.run()启动主协程,主协程会在await close_future处阻塞直到fd关闭,协程执行结束后事件循环会自动退出,不需要手动调用停止方法。 - 额外注意:原示例代码中
asyncio.get_event_loop().loop.add_reader属于冗余写法,get_event_loop()返回的就是事件循环实例,直接调用add_reader方法即可。
内容的提问来源于stack exchange,提问作者user1201614
相关产品推荐
相关产品推荐

