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

python-telegram-bot中InlineKeyboard点击后CallbackQueryHandler未触发

问题:python-telegram-bot内联键盘点击后无响应,button函数不触发

使用python-telegram-bot开发Telegram机器人时,添加InlineKeyboard后,点击任意按钮都无法触发关联的button()回调处理函数。

相关代码如下:

from telegram import *
from telegram.ext import *

print('bot executed')
token = <BOT_TOKEN>


async def send_message_in_channel(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    global new_data
    await context.bot.send_message(chat_id=<CHANNEL_USERNAME>, text="new_data")


async def message(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    await context.bot.delete_message(update.effective_chat.id, message_id=update.message.id)


async def button(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    query = update.callback_query
    await query.answer()
    print('button reached')
    if query.data == 'True':
        print("choose yes")
        await send_message_in_channel(update, context)
    elif query.data == 'False':
        print("choose no")

async def option(new_data) -> None:
    bot = Bot(token=token)
    options = [
        [
            InlineKeyboardButton('Yes, Post It', callback_data="True"),
            InlineKeyboardButton('No, Don\'t Post', callback_data="False")
        ],
    ]

    reply_markup = InlineKeyboardMarkup(options)
    await bot.send_message(chat_id=<MY_OWN_CHAT_ID>, text=new_data, reply_markup=reply_markup, disable_web_page_preview=True)


if __name__ == '__main__':
    new_data = ''
    
    application = ApplicationBuilder().token(token).build()
    application.add_handler(CallbackQueryHandler(button))
    application.add_handler(MessageHandler(
        filters.TEXT & (~filters.COMMAND), message))
    application.run_polling()

注:option()函数由外部传入new_data调用,此前通过CommandHandler从机器人内部调用时功能正常,但外部调用时无法获取update或context对象,修改button()的context类型也无法解决问题。


原因分析

问题核心在于外部调用option()时,使用了独立创建的Bot实例发送消息。当前运行的Application仅会处理自身管理的bot实例产生的更新,而你手动创建的Bot(token=token)与Application无关联,导致该消息的回调查询无法被CallbackQueryHandler捕获。

之前通过CommandHandler调用正常,是因为此时可以通过context.bot获取Application管理的bot实例,发送的消息回调能被正确路由到处理函数。


解决方案

提供两种可行的修复方式:

方式一:通过Application的bot实例发送消息

修改option()函数,接收application作为参数,使用其管理的bot对象发送消息,避免创建独立Bot实例:

async def option(new_data, application: Application) -> None:
    options = [
        [
            InlineKeyboardButton('Yes, Post It', callback_data="True"),
            InlineKeyboardButton('No, Don\'t Post', callback_data="False")
        ],
    ]
    reply_markup = InlineKeyboardMarkup(options)
    # 使用Application管理的bot发送消息
    await application.bot.send_message(chat_id=<MY_OWN_CHAT_ID>, text=new_data, reply_markup=reply_markup, disable_web_page_preview=True)

外部调用时,直接传入启动后的application对象:

if __name__ == '__main__':
    new_data = ''
    
    application = ApplicationBuilder().token(token).build()
    application.add_handler(CallbackQueryHandler(button))
    application.add_handler(MessageHandler(
        filters.TEXT & (~filters.COMMAND), message))
    
    # 外部调用示例(需在异步上下文执行)
    import asyncio
    asyncio.create_task(option("测试内容", application))
    
    application.run_polling()

方式二:利用Application的上下文池访问bot

如果外部调用无法直接传递application,可将application声明为全局变量,通过其上下文池获取bot实例:

# 声明全局application变量
application = None

async def option(new_data) -> None:
    global application
    # 通过上下文池获取Application管理的bot
    async with application.bot:
        options = [
            [
                InlineKeyboardButton('Yes, Post It', callback_data="True"),
                InlineKeyboardButton('No, Don\'t Post', callback_data="False")
            ],
        ]
        reply_markup = InlineKeyboardMarkup(options)
        await application.bot.send_message(chat_id=<MY_OWN_CHAT_ID>, text=new_data, reply_markup=reply_markup, disable_web_page_preview=True)

if __name__ == '__main__':
    new_data = ''
    
    global application
    application = ApplicationBuilder().token(token).build()
    application.add_handler(CallbackQueryHandler(button))
    application.add_handler(MessageHandler(
        filters.TEXT & (~filters.COMMAND), message))
    
    # 外部调用示例
    import asyncio
    asyncio.create_task(option("测试内容"))
    
    application.run_polling()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 08:47:34