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

Flask/LangChain/asyncio应用中"Event loop is closed"错误排查与解决

问题背景

使用Flask(已安装async扩展)、LangChain和asyncio技术栈,目标是并行执行多个LLM请求。

问题现象

应用每处理两次请求,终端会抛出与analyses列表项数量一致的错误:

ERROR:asyncio:Task exception was never retrieved
future: <Task finished name='Task-44' coro=<AsyncClient.aclose() done, defined at [path]\flask-server\venv\Lib\site-packages\httpx\_client.py:2011> exception=RuntimeError('Event loop is closed')>
[Traceback without references to application files]
RuntimeError: Event loop is closed

该错误不影响应用正常返回响应,但需解决。

疑问
  1. 如何避免此RuntimeError?
  2. 问题根源是什么?哪些事件循环在何时被关闭,为何会引发问题?
相关代码
# logic
import asyncio

async def run_analyses(analyses):
    tasks = []
    for analysis in analyses:
        task = asyncio.create_task(run_analysis(analysis))
        tasks.append(task)
    results = await asyncio.gather(*tasks)
    return results

async def run_analysis(analysis):
    messages = ...
    llm = ChatAnthropic(...)
    response = await llm.ainvoke(messages)
    result = response.content
    return result

# app.py using Flask
import asyncio

@app.route('/process', methods=['POST'])
async def process():
    data = request.json
    analyses = data['analyses']
    results = await run_analyses(analyses)
    return jsonify(results)

if __name__ == '__main__':
    app.run(debug=True, port=5000)
已尝试方案
  • 尝试await主程序的app.run
  • 添加/移除asyncio.create_task
  • 按照GPT4建议操作1小时但无效
问题根源分析
  1. 事件循环生命周期不匹配:Flask的debug模式默认启用自动重载机制,每次触发重载时,旧事件循环会被关闭,但LangChain的ChatAnthropic内部使用的httpx.AsyncClient后台仍有未完成的aclose()关闭任务,这些任务在旧循环关闭后才执行,导致抛出Event loop is closed错误。
  2. 客户端实例重复创建:run_analysis函数每次调用都会新建ChatAnthropic实例,每个实例对应独立的AsyncClient。请求完成后,客户端的关闭任务被加入事件循环,若此时循环因Flask重载提前关闭,就会触发错误。
解决方法

方法1:禁用Flask的debug模式

debug模式的自动重载是触发问题的核心,关闭后事件循环会保持稳定:

if __name__ == '__main__':
    app.run(debug=False, port=5000)

方法2:复用LLM客户端实例

避免每次请求新建ChatAnthropic实例,复用客户端可减少后台关闭任务,同时提升性能:

# 全局复用LLM客户端
llm = ChatAnthropic(...)

async def run_analysis(analysis):
    messages = ...
    response = await llm.ainvoke(messages)
    result = response.content
    return result

方法3:手动管理事件循环(适配debug模式)

若必须使用debug模式,可手动创建并维护事件循环,避免Flask自动管理的冲突:

import asyncio
from flask import Flask

app = Flask(__name__)

@app.route('/process', methods=['POST'])
async def process():
    data = request.json
    analyses = data['analyses']
    results = await run_analyses(analyses)
    return jsonify(results)

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    try:
        loop.run_until_complete(app.run(debug=True, port=5000))
    finally:
        loop.close()

方法4:捕获客户端关闭异常(临时兜底)

通过包装ainvoke方法或修改客户端配置,确保aclose()任务即使在循环关闭时也不会抛出未处理异常(不推荐作为主要解决方案)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 09:05:31