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

Flask异步函数导致Telegram Bot仅能获取单个文件属性的问题

解决Telegram Bot接收文件时的Event loop is closed错误

我用Flask搭建Telegram Bot实现接收客户端文件的功能,首次接收文件时正常,但第二次请求开始触发RuntimeError: Event loop is closed错误,错误发生在file_info = await bot.get_file(file_id)代码行。

原代码

from flask import Flask, request
import asyncio
import telegram

app = Flask(__name__)
bot = telegram.Bot(token=TOKEN)

# Recieve files from Telegram
@app.route('/', methods=['POST'])
def handle_request():
    data = request.get_json()
    file_id = data['message']['document']['file_id']
    
    async def get_path (file_id):
        global file_info
        file_info = await bot.get_file (file_id)
        return file_info

    loop = asyncio.new_event_loop()
    logging.info(f"loop={loop}")
    asyncio.run (get_path(file_id))
    logging.info (f"file_path={file_info.file_path}") 

# launch Flask
if __name__ == '__main__':
    app.run(debug=True)

首次执行结果

INFO 83: loop=<UnixSelectorEventLoop running=False closed=False debug=False>
INFO 113: file_path=https://api.telegram.org/file/bot557***:***VF0FrPEGq9CnchBHQ4IMzR4oAY/documents/file_28.xlsx

错误日志

Exception on / [POST]:
Traceback (most recent call last):
File "/home/proj/venv/lib/python3.10/site-packages/telegram/request/_baserequest.py", line 274, in _request_wrapper
     code, payload = await self.do_request(
File "/home/proj/venv/lib/python3.10/site-packages/telegram/request/_httpxrequest.py", line 199, in do_request
     res = await self._client.request(
File "/home/proj/venv/lib/python3.10/site-packages/httpx/_client.py", line 1533, in request
     return await self.send(request, auth=auth, follow_redirects=follow_redirects)
File "/home/proj/venv/lib/python3.10/site-packages/httpx/_client.py", line 1620, in send
     response = await self._send_handling_auth(
File "/home/proj/venv/lib/python3.10/site-packages/httpx/_client.py", line 1648, in _send_handling_auth
     response = await self._send_handling_redirects(
File "/home/proj/venv/lib/python3.10/site-packages/httpx/_client.py", line 1685, in _send_handling_redirects
     response = await self._send_single_request(request)
File "/home/proj/venv/lib/python3.10/site-packages/httpx/_client.py", line 1722, in _send_single_request
     response = await transport.handle_async_request(request)
File "/home/proj/venv/lib/python3.10/site-packages/httpx/_transports/default.py", line 353, in handle_async_request
     resp = await self._pool.handle_async_request(req)
File "/home/proj/venv/lib/python3.10/site-packages/httpcore/_async/connection_pool.py", line 220, in handle_async_request
     await self._close_expired_connections()
File "/home/proj/venv/lib/python3.10/site-packages/httpcore/_async/connection_pool.py", line 188, in _close_expired_connections
     await connection.aclose()
File "/home/proj/venv/lib/python3.10/site-packages/httpcore/_async/connection.py", line 159, in aclose
     await self._connection.aclose()
File "/home/proj/venv/lib/python3.10/site-packages/httpcore/_async/http2.py", line 313, in aclose
     await self._network_stream.aclose()
File "/home/proj/venv/lib/python3.10/site-packages/httpcore/backends/asyncio.py", line 54, in aclose
     await self._stream.aclose()
File "/home/proj/venv/lib/python3.10/site-packages/anyio/streams/tls.py", line 192, in aclose
     await self.transport_stream.aclose()
File "/home/proj/venv/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 1323, in aclose
     self._transport.close()
File "/usr/lib/python3.10/asyncio/selector_events.py", line 706, in close
     self._loop.call_soon(self._call_connection_lost, None)
File "/usr/lib/python3.10/asyncio/base_events.py", line 753, in call_soon
     self._check_closed()
File "/usr/lib/python3.10/asyncio/base_events.py", line 515, in _check_closed
     raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed

问题根源

asyncio.run()会在协程执行完毕后自动关闭事件循环,而全局的telegram.Bot实例内部的HTTP客户端会复用连接池。第二次请求时,连接池尝试使用已被关闭的事件循环,从而触发报错。

修复方案

方案1:每次请求创建新Bot实例(适合小流量场景)

将Bot实例的创建移到请求处理函数内部,避免复用旧的连接池和事件循环:

from flask import Flask, request
import asyncio
import telegram
import logging

app = Flask(__name__)
TOKEN = "你的BotToken"

@app.route('/', methods=['POST'])
def handle_request():
    data = request.get_json()
    file_id = data['message']['document']['file_id']
    
    async def get_path(file_id):
        # 每次请求创建新的Bot实例
        bot = telegram.Bot(token=TOKEN)
        file_info = await bot.get_file(file_id)
        return file_info

    file_info = asyncio.run(get_path(file_id))
    logging.info(f"file_path={file_info.file_path}") 
    return "OK"

if __name__ == '__main__':
    logging.basicConfig(level=logging.INFO)
    app.run(debug=True)

方案2:使用异步Flask(适合高流量场景)

改用flask-asyncio扩展实现异步请求处理,保持Bot实例复用的同时,让事件循环持续运行:

from flask import Flask, request
import asyncio
import telegram
import logging
from flask_asyncio import AsyncFlask

app = AsyncFlask(__name__)
TOKEN = "你的BotToken"
# 全局复用Bot实例
bot = telegram.Bot(token=TOKEN)

@app.route('/', methods=['POST'])
async def handle_request():
    data = request.get_json()
    file_id = data['message']['document']['file_id']
    
    file_info = await bot.get_file(file_id)
    logging.info(f"file_path={file_info.file_path}") 
    return "OK"

if __name__ == '__main__':
    logging.basicConfig(level=logging.INFO)
    app.run(debug=True)

注意:方案2需要先安装flask-asyncio,执行命令:pip install flask-asyncio

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 21:53:25