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

Python Telegram Bot v20异步运行阻塞及EventLoop报错求助

问题:Python Telegram Bot v20 耗时任务阻塞及事件循环绑定错误

问题现象

使用Python Telegram Bot v20开发的机器人执行耗时任务时,会完全停止响应其他用户;尝试通过线程嵌套异步逻辑解决时,出现事件循环绑定错误:

telegram.error.NetworkError: Unknown error in HTTP implementation: RuntimeError('<asyncio.locks.Event object at 0x0000022361E0A920 [unset]> is bound to a different event loop')

最简复现代码

from telegram import Update
from telegram.ext import ApplicationBuilder, CommandHandler, ContextTypes
import time

async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    await update.message.reply_text("start")
    time.sleep(10)  # 模拟耗时任务
    await update.message.reply_text("finish")

app = ApplicationBuilder().token("TOKEN HERE").build()
app.add_handler(CommandHandler("start", start))
app.run_polling()

错误原因

  1. 同步阻塞导致事件循环卡主:time.sleep()是同步阻塞函数,会占用asyncio的主事件循环,使其无法处理其他用户的请求。
  2. 线程方案的逻辑错误:手动创建新事件循环并在其中执行Telegram API调用,而Update、Context等对象绑定在机器人的主事件循环上,跨事件循环操作会触发绑定错误。

有效解决方案

方案1:用asyncio.run_in_executor处理同步耗时任务

将阻塞的同步任务提交到线程池/进程池执行,不占用主事件循环,同时所有Telegram API调用保持在主循环中:

from telegram import Update
from telegram.ext import ApplicationBuilder, CommandHandler, ContextTypes
import time
import asyncio
from concurrent.futures import ThreadPoolExecutor

# 初始化线程池,可根据任务数量调整max_workers
thread_pool = ThreadPoolExecutor(max_workers=4)

async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    await update.message.reply_text("start")
    
    # 将耗时同步任务交给线程池执行
    await asyncio.get_event_loop().run_in_executor(
        thread_pool,
        time.sleep,  # 替换为你的实际耗时函数
        10
    )
    
    await update.message.reply_text("finish")

app = ApplicationBuilder().token("TOKEN HERE").build()
app.add_handler(CommandHandler("start", start))
app.run_polling()

方案2:改用异步版本的耗时任务

如果你的耗时任务支持异步改写(比如网络请求用aiohttp,等待用asyncio.sleep),直接使用异步函数即可:

from telegram import Update
from telegram.ext import ApplicationBuilder, CommandHandler, ContextTypes
import asyncio

async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    await update.message.reply_text("start")
    await asyncio.sleep(10)  # 异步等待,不阻塞事件循环
    await update.message.reply_text("finish")

app = ApplicationBuilder().token("TOKEN HERE").build()
app.add_handler(CommandHandler("start", start))
app.run_polling()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 08:43:41