async-dns库查询函数单会话仅可调用一次报Event loop closed错误如何解决
问题原因
async-dns库的UDP请求调度器是全局单例实例,第一次运行查询时会绑定当前事件循环的传输层资源。asyncio.run()执行完毕后会彻底关闭当前事件循环,第二次运行时调度器仍然持有已经失效的旧传输层/事件循环引用,就会抛出空属性、事件循环已关闭类错误。
解决方法
方案1:每次查询后手动释放调度器资源
在查询逻辑末尾主动调用UDP调度器的关闭方法,清空全局持有的资源,适合需要多次调用asyncio.run()的场景:
import asyncio from async_dns.core import types, Address from async_dns.resolver import DNSClient from async_dns.request import udp async def query(): client = DNSClient() res = await client.query('www.google.com', types.A, Address.parse('8.8.8.8')) print(res) print(res.aa) # 手动关闭UDP调度器释放绑定的旧资源 await udp.dispatcher.close() # 多次运行也不会报错 asyncio.run(query()) asyncio.run(query())
方案2:复用同一个事件循环执行所有查询
不要多次调用asyncio.run(),把所有查询任务都放在同一个事件循环里执行,性能更好适合批量查询场景:
import asyncio from async_dns.core import types, Address from async_dns.resolver import DNSClient async def query(): client = DNSClient() res = await client.query('www.google.com', types.A, Address.parse('8.8.8.8')) print(res) print(res.aa) async def main(): # 所有查询都在同一个事件循环内执行 await query() await query() asyncio.run(main())
Windows系统额外适配
如果是Windows环境,在代码最开头加上以下配置,避免事件循环策略导致的额外报错:
import asyncio asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
内容的提问来源于stack exchange,提问作者Ξένη Γήινος
相关产品推荐
相关产品推荐

