You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Firestore AsyncClient调用API时报事件循环关闭及协程未等待错误

问题本质

你遇到的是asyncio.run重复调用 + gRPC异步客户端隐式复用旧事件循环导致的运行时错误,核心报错为Event loop is closed。


错误产生的原因

  • asyncio.run的工作逻辑:每次调用都会创建一个全新的事件循环,运行完传入的协程后会彻底关闭当前循环。你在Test.__init__里调用了一次asyncio.run,运行完第一个Firestore请求后,第一个事件循环就已经被销毁关闭。
  • Google Cloud Firestore异步客户端(以及底层依赖的gRPC异步通道)的特性:AsyncClient实例在第一次调用API时,会绑定当前运行的事件循环,且后续所有请求都会默认复用这个绑定的循环,不会自动检测新的循环。
  • 替换成asyncio.sleep能正常运行的原因:asyncio.sleep是纯asyncio标准库实现,每次调用都会自动绑定当前活跃的新循环,没有第三方客户端的全局/实例级循环绑定逻辑,所以不会触发错误。
  • 代码触发路径:第一次Test实例化调用asyncio.run时,Fire2封装的AsyncClient绑定了第一个临时循环,循环运行完被关闭;之后调用test方法实例化Test2,第二次调用asyncio.run创建了新的循环,但Firestore客户端还是尝试往已经关闭的第一个循环里提交gRPC请求任务,直接触发循环已关闭的报错。

修复方案

不要在业务逻辑里多次调用asyncio.run,整个程序入口只调用一次asyncio.run,把所有异步逻辑都放到入口协程里运行,参考代码如下:

import asyncio
import Fire2

class Test:
    async def init_async(self):
        doc = await self.wait()
        return doc

    async def wait(self):
        doc = await Fire2("test1").get(g1)
        return doc

    async def test(self):
        x = await Test2().run_async(p1)

class Test2:
    async def run_async(self, p):
        doc = await Fire2('test2').get(p)
        print(doc.to_dict())
        return doc

p1 = 'foo'
g1 = 'bar'

# 全局仅调用一次asyncio.run
async def main():
    h = Test()
    await h.init_async()
    await h.test()

if __name__ == "__main__":
    asyncio.run(main())

如果确实需要多场景使用独立循环,每次使用完AsyncClient后主动调用客户端的close()方法释放资源,下次使用时重新初始化新的AsyncClient实例,避免旧实例绑定已关闭的循环。


内容的提问来源于stack exchange,提问作者weasel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 14:09:03