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

Python Telegram机器人多用户兼容问题求助:仅首个用户可接收消息

解决Python Telegram机器人多用户问题的方案

问题根源

你的三个问题本质是两个核心问题:

  • 单用户ID绑定:代码中只存储了第一个启动机器人用户的chat_id,没有维护多用户列表
  • 同步阻塞架构:使用同步版Telegram库或同步处理逻辑,导致单线程无法同时响应多个用户请求,甚至引发用户ID冲突

具体修复步骤

1. 切换到异步Telegram库

放弃旧版同步python-telegram-bot,使用v20+的异步版本(完全基于asyncio),异步架构天然支持多用户并发,不会阻塞消息处理。

2. 维护多用户注册列表

用集合存储所有启动过机器人的用户chat_id,避免覆盖或丢失用户:

# 全局存储已注册用户ID,自动去重
registered_users = set()

在/start命令中添加用户到列表:

async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
    chat_id = update.effective_chat.id
    registered_users.add(chat_id)
    await update.message.reply_text("已完成注册,将收到提醒消息")

3. 异步批量发送提醒

发送警报或课程提醒时,遍历所有注册用户异步发送:

async def broadcast_alert(context: ContextTypes.DEFAULT_TYPE, alert_content: str):
    # 遍历集合副本,避免遍历过程中修改集合引发异常
    for chat_id in list(registered_users):
        try:
            await context.bot.send_message(chat_id=chat_id, text=alert_content)
        except Exception as e:
            print(f"发送给用户 {chat_id} 失败: {str(e)}")
            # 移除无效用户ID
            registered_users.discard(chat_id)

4. 消除同步阻塞操作

如果有耗时逻辑(如数据库查询、API调用),必须用异步方式处理:

  • 用aiohttp替代requests发起HTTP请求
  • 用asyncio.sleep()替代time.sleep()
  • 同步耗时函数用await asyncio.to_thread(your_sync_func)包装,避免阻塞事件循环

完整可运行示例代码

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

# 存储所有已注册用户的chat_id
registered_users = set()

async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
    chat_id = update.effective_chat.id
    registered_users.add(chat_id)
    await update.message.reply_text("已注册成功,将及时推送警报和课程提醒")

async def send_air_raid_alert(context: ContextTypes.DEFAULT_TYPE):
    """模拟空袭警报推送"""
    await broadcast_alert(context, "⚠️ 空袭警报!请立即前往安全区域躲避!")

async def send_class_reminder(context: ContextTypes.DEFAULT_TYPE):
    """模拟课程提醒推送"""
    await broadcast_alert(context, "📚 10分钟后有课程,请做好准备!")

async def broadcast_alert(context: ContextTypes.DEFAULT_TYPE, alert_content: str):
    for chat_id in list(registered_users):
        try:
            await context.bot.send_message(chat_id=chat_id, text=alert_content)
        except Exception as e:
            print(f"消息发送失败(用户 {chat_id}): {str(e)}")
            registered_users.discard(chat_id)

def main():
    # 替换为你的机器人Token
    BOT_TOKEN = "your_bot_token"
    app = ApplicationBuilder().token(BOT_TOKEN).build()

    # 注册/start命令处理器
    app.add_handler(CommandHandler("start", start))

    # 配置定时任务(示例:每天10点发送课程提醒)
    job_queue = app.job_queue
    job_queue.run_daily(send_class_reminder, time=time(hour=10, minute=0))

    # 启动机器人
    app.run_polling()

if __name__ == "__main__":
    main()

解决你之前的asyncio问题

如果之前用asyncio踩坑,大概率是这几个原因:

  • 在异步函数中调用了同步阻塞方法(如requests.get()),需替换为异步实现
  • 手动管理事件循环出错,python-telegram-bot的run_polling()会自动处理事件循环,无需手动启动
  • 没有用await调用异步函数,导致逻辑不执行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 14:29:49