Python实现Telegram Bot周期性消息遇409冲突错误求排查
我尝试实现一个Telegram Bot,让账号定期接收更新消息,但执行时遇到如下错误:
telebot.apihelper.ApiTelegramException: A request to the Telegram API was unsuccessful. Error code: 409. Description: Conflict: terminated by other getUpdates request; make sure that only one bot instance is running
我的代码如下:
import threading import telebot import Consts from mypackage.ProcessManager import ProcessManager bot = telebot.TeleBot(Consts.bot_token, threaded=True) process_manager = ProcessManager() @bot.message_handler(commands=['subscribe']) def subscribe(message): chat_id = message.from_user.id if not process_manager.has_running_elements(chat_id): process_manager.start_process(chat_id=chat_id, target=send_message, arg2=chat_id, arg3="Prova") bot.reply_to(message, "Perfetto. Da ora riceverai aggiornamenti sulla tua assicurazione") else: bot.reply_to(message, "Sei già iscritto") def send_message(chat_id, message: str): bot.send_message(chat_id=chat_id, text=message) bot.infinity_polling()
ProcessManager是一个管理multiprocessing.Process对象的包装类,其start_process函数代码如下:
def start_process(self, chat_id, target, **args): new_process = multiprocessing.Process(target=target, daemon=True, args=args) self.processes_dict[chat_id] = new_process new_process.start()
请问我哪里出错了?
错误原因
409错误的核心是多个Telegram Bot实例同时调用getUpdates接口,触发Telegram服务器的冲突判定。
你的代码存在两个关键问题:
- 未用
if __name__ == '__main__':包裹bot.infinity_polling():在Windows系统中,multiprocessing采用spawn模式创建子进程,会重新执行整个脚本的顶层代码。这导致每个子进程都会初始化新的bot实例并启动轮询,多个实例同时请求更新引发冲突。 - 子进程共享父进程的
bot对象:multiprocessing的进程拥有独立内存空间,父进程的bot会被复制到子进程,但Telebot的实例并非进程安全,这种共享会引发包括重复轮询在内的各种问题。
解决方案
方案1:改用线程替代进程
如果你的定时任务仅需发送消息(无需独立CPU资源),线程是更合适的选择——线程共享同一内存空间,不会重复初始化bot实例:
修改ProcessManager的start_process方法,改用threading.Thread:
def start_process(self, chat_id, target, **args): new_thread = threading.Thread(target=target, daemon=True, args=args) self.processes_dict[chat_id] = new_thread new_thread.start()
方案2:修复进程模式的问题
若必须使用进程,需做两处修改:
- 将
bot.infinity_polling()限制在主进程执行:
if __name__ == '__main__': bot.infinity_polling()
- 在子进程的
send_message中单独初始化bot,避免共享父进程实例:
def send_message(chat_id, message: str): # 子进程内独立初始化bot bot = telebot.TeleBot(Consts.bot_token) bot.send_message(chat_id=chat_id, text=message)
额外建议
如果是实现定期推送功能,更推荐使用Telebot内置的telebot.util.repeat装饰器,或threading.Timer来周期性执行任务,无需手动管理进程/线程,从根源避免多实例冲突。
内容的提问来源于stack exchange,提问作者Fabrizio Gabriele

