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

Flask搭配异步Firestore客户端二次加载页面时出现Event loop is closed错误

Flask + Async Firestore 客户端:解决"Event loop is closed"错误

问题现象

运行结合firestore_async的Flask应用时,首次加载页面正常,第二次加载触发Event loop is closed运行时错误;使用WSGI worker时错误偶现;尝试为每个请求创建新客户端也无法解决。

示例复现代码:

import firebase_admin
from firebase_admin import credentials, firestore_async
from flask import Flask

cred = credentials.Certificate('credentials.json')
firebase_admin.initialize_app(cred)
db = firestore_async.client()

app = Flask(__name__)

@app.route('/')
async def hello_world():
    await db.collection("product").get()
    return 'Hello, World!'

if __name__ == "__main__":
    app.run(debug=True)

问题根源

  1. Flask debug模式的重载器:Werkzeug开发服务器在debug模式下默认启动进程重载器,重载后原进程的事件循环被关闭,但Firestore异步客户端会缓存旧的事件循环引用,导致后续请求调用已关闭的循环。
  2. Flask原生运行方式的限制:app.run()处理async视图时会创建临时事件循环,但Firestore客户端的内部逻辑会绑定全局循环,循环被回收后无法自动重建绑定。

解决方案

1. 关闭debug模式的重载器(开发环境快速修复)

修改启动代码,禁用进程重载器,避免事件循环被重复关闭:

if __name__ == "__main__":
    app.run(debug=True, use_reloader=False)

2. 使用ASGI服务器(生产/稳定开发环境推荐)

Flask的async视图需要ASGI服务器来正确管理事件循环,推荐使用hypercorn或uvicorn:

  • 先安装依赖:
    pip install hypercorn
    
  • 修改启动逻辑,用ASGI方式运行:
    import firebase_admin
    from firebase_admin import credentials, firestore_async
    from flask import Flask
    from hypercorn.asyncio import serve
    from hypercorn.config import Config
    import asyncio
    
    cred = credentials.Certificate('credentials.json')
    firebase_admin.initialize_app(cred)
    db = firestore_async.client()
    
    app = Flask(__name__)
    
    @app.route('/')
    async def hello_world():
        await db.collection("product").get()
        return 'Hello, World!'
    
    if __name__ == "__main__":
        config = Config()
        config.bind = ["0.0.0.0:5000"]
        config.debug = True
        asyncio.run(serve(app, config))
    

3. 为每个请求绑定活跃事件循环(保留重载器的场景)

通过Flask的请求钩子,在每次请求前确保Firestore客户端绑定当前活跃的事件循环:

import firebase_admin
from firebase_admin import credentials, firestore_async
from flask import Flask, g
import asyncio

cred = credentials.Certificate('credentials.json')
firebase_admin.initialize_app(cred)

app = Flask(__name__)

@app.before_request
def setup_firestore():
    # 为每个请求创建新的客户端,绑定当前请求的事件循环
    g.db = firestore_async.client()

@app.route('/')
async def hello_world():
    await g.db.collection("product").get()
    return 'Hello, World!'

if __name__ == "__main__":
    app.run(debug=True)

注意:firebase_admin.initialize_app只能执行一次,不要放在请求钩子中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 12:50:03