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

python-telegram-bot调用run_polling时错误无法输出至控制台求助

问题解决方法

核心原因分析

  1. 错误处理器不触发:你直接在测试函数中抛出的BaseException不属于python-telegram-bot框架的错误处理范畴——框架的error_handler仅捕获bot处理更新(如命令、消息、回调)过程中产生的异常,测试主线程直接抛出的错误不会被它拦截。
  2. 控制台卡住+错误被掩盖:application.updater.start_polling()会启动后台异步任务,当你直接抛出错误后,测试框架终止该任务时会触发asyncio.CancelledError,相关日志会覆盖你的原始错误信息,导致控制台卡住且看不到实际错误。

具体解决方案

方案1:先优雅停止Bot,再抛出错误

在抛出测试错误前,先关闭Bot的所有后台任务,避免CancelledError干扰错误显示:

async def test(self):
    logging.basicConfig(level=logging.DEBUG)
    application = (
        Application
        .builder()
        .token('MY_TELEGRAM_BOT_TOKEN')
        .build()
    )
    application.add_error_handler(error_handler)
    
    await application.initialize()
    await application.start()
    await application.updater.start_polling()
    
    try:
        # 这里放置需要测试的逻辑或直接抛出错误
        raise BaseException('my error')
    finally:
        # 必须先停止Bot任务,避免取消日志掩盖错误
        await application.updater.stop()
        await application.stop()
        await application.shutdown()

方案2:测试Bot内部逻辑的错误(触发error_handler)

如果是要测试Bot命令/回调函数中的错误,需要构造模拟更新并交给Bot处理,这样error_handler才会捕获异常:

from telegram import Update, Message, Chat
from telegram.ext import CommandHandler

# 定义一个会抛出错误的命令处理器
async def bad_command(update, context):
    raise BaseException('command error')

async def test(self):
    logging.basicConfig(level=logging.DEBUG)
    application = (
        Application
        .builder()
        .token('MY_TELEGRAM_BOT_TOKEN')
        .build()
    )
    application.add_error_handler(error_handler)
    application.add_handler(CommandHandler('bad', bad_command))  # 添加错误处理器
    
    await application.initialize()
    await application.start()
    
    # 构造模拟更新,触发错误命令
    update = Update(update_id=1, message=Message(text='/bad', chat=Chat(id=123, type='private')))
    await application.process_update(update)  # 处理更新,此时error_handler会触发
    
    await application.updater.stop()
    await application.stop()
    await application.shutdown()

方案3:手动捕获并打印原始错误

如果需要强制显示测试中的错误,可以手动捕获后打印回溯,再重新抛出给unittest:

async def test(self):
    logging.basicConfig(level=logging.DEBUG)
    application = (
        Application
        .builder()
        .token('MY_TELEGRAM_BOT_TOKEN')
        .build()
    )
    application.add_error_handler(error_handler)
    
    await application.initialize()
    await application.start()
    await application.updater.start_polling()
    
    try:
        raise BaseException('my error')
    except BaseException as e:
        # 手动打印错误和回溯
        print(f"实际错误内容: {e}")
        import traceback
        traceback.print_exc()
        raise  # 重新抛出让unittest捕获
    finally:
        await application.updater.stop()
        await application.stop()
        await application.shutdown()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 03:07:54