如何在Python的Telebot中同时运行多个任务?
在Telebot中同时运行bot轮询和自定义任务的解决方案
Telebot是同步库,bot.polling()是阻塞式调用,会占满主线程,所以直接用asyncio.gather()无法同时运行它和同步任务。下面提供两种可行的实现方式:
方案一:使用线程(最简单直接)
把bot.polling()放到独立线程中运行,主线程执行自定义任务,两者互不阻塞。
import telebot import threading import time # 按需导入数据库驱动,比如pymongo from pymongo import MongoClient # 初始化配置 TOKEN = "你的机器人Token" LOG_CHAT_ID = 123456789 # 日志接收的聊天ID DB_URI = "你的数据库连接地址" bot = telebot.TeleBot(TOKEN) db_client = MongoClient(DB_URI) db = db_client["你的数据库名"]["你的集合名"] def custom_task(): # 你的任务逻辑,这里示例是查询数据库并发送日志 data = "" for item in list(db.find()): data += f"{item['id']}: {item['data']}\n" if data: bot.send_message(LOG_CHAT_ID, data) # 如果需要循环执行,取消下面的注释并调整间隔 # while True: # data = "" # for item in list(db.find()): # data += f"{item['id']}: {item['data']}\n" # if data: # bot.send_message(LOG_CHAT_ID, data) # time.sleep(60) # 每60秒执行一次 def run_bot_polling(): # none_stop=True保证断连后自动重连 bot.polling(none_stop=True) if __name__ == '__main__': print("working..") # 启动bot轮询线程 bot_thread = threading.Thread(target=run_bot_polling) bot_thread.daemon = True # 主线程结束时自动终止bot线程 bot_thread.start() # 执行自定义任务 custom_task()
方案二:用asyncio包装同步函数(保留异步风格)
通过ThreadPoolExecutor把同步的bot.polling()和自定义任务包装成可在asyncio中运行的异步任务,实现多任务并发。
import telebot import asyncio from concurrent.futures import ThreadPoolExecutor from pymongo import MongoClient # 初始化配置 TOKEN = "你的机器人Token" LOG_CHAT_ID = 123456789 DB_URI = "你的数据库连接地址" bot = telebot.TeleBot(TOKEN) db_client = MongoClient(DB_URI) db = db_client["你的数据库名"]["你的集合名"] def sync_custom_task(): data = "" for item in list(db.find()): data += f"{item['id']}: {item['data']}\n" if data: bot.send_message(LOG_CHAT_ID, data) def sync_bot_polling(): bot.polling(none_stop=True) async def main(): print("working..") # 创建线程池,最多同时运行2个线程 executor = ThreadPoolExecutor(max_workers=2) loop = asyncio.get_running_loop() # 提交两个同步任务到线程池,用asyncio.gather并发执行 await asyncio.gather( loop.run_in_executor(executor, sync_bot_polling), loop.run_in_executor(executor, sync_custom_task) ) if __name__ == '__main__': asyncio.run(main())
注意事项
- 如果自定义任务需要循环执行,务必添加休眠逻辑(
time.sleep()或asyncio.sleep()),避免频繁占用CPU或数据库连接。 - Telebot的大部分API方法(如
send_message)是线程安全的,但如果涉及复杂的状态操作,建议添加线程锁避免冲突。 - 方案一中的
daemon=True设置可确保主线程退出时,bot线程自动终止,避免程序残留进程。
内容的提问来源于stack exchange,提问作者Emir
相关产品推荐
相关产品推荐

