使用asyncio.run启动aiocoap服务器报错RuntimeError: Event loop is closed
问题原因
Event loop is closed报错核心有两个诱因:
- 原代码逻辑问题:
main函数中仅等待了CoAP服务上下文创建的任务,该任务完成后main协程立刻退出,asyncio.run()会直接销毁事件循环;而aiocoap的传输层对象析构逻辑需要调用事件循环接口,此时循环已经关闭就会触发报错。此外原代码中add_resource传入的是CoAPServer类而非类实例,也会导致请求处理异常。 - 版本兼容问题:Python 3.8的
asyncio.run()在结束时会强制关闭所有循环资源,不会等待异步对象的析构逻辑执行完成,和旧版本aiocoap的资源清理逻辑存在兼容冲突。
解决方法
- 方案1:调整main协程逻辑,保持服务长期运行
修改后的代码如下:
import asyncio import aiocoap import aiocoap.resource as resource class CoAPServer(resource.Resource): def __init__(self) -> None: super().__init__() async def render_get(self, request): print("Received GET request ...") return aiocoap.Message(code=aiocoap.GET, payload="hello friend".encode('utf8')) async def render_post(self, request): print("Received POST request ...") return aiocoap.Message(code=aiocoap.CHANGED, payload="that's me".encode('utf8')) async def main(): root = resource.Site() # 传入类实例而非类本身 root.add_resource(['demo'], CoAPServer()) await aiocoap.Context.create_server_context(root, bind=('127.0.0.1', 5683)) # 新增永久等待逻辑,避免协程提前退出 stop_event = asyncio.Event() await stop_event.wait() if __name__ == "__main__": asyncio.run(main())
- 方案2:升级依赖版本
升级aiocoap到最新正式版,同时将Python升级到3.9及以上版本,该兼容问题在高版本中已经被修复。 - 方案3:保留run_forever写法
对于长期运行的服务类程序,asyncio.get_event_loop().run_forever()在Python 3.8环境下没有功能性问题,可继续使用。
内容的提问来源于stack exchange,提问作者Giulio Barabino
相关产品推荐
相关产品推荐

