如何实现Pyrogram机器人多进程并行处理命令?
问题分析
你的问题根源在于同步阻塞函数占用了Pyrogram的异步事件循环。Pyrogram基于asyncio,事件循环是单线程的:当/TASK1里调用first_def()、second_def()这些耗时的同步函数时,整个事件循环会被卡住,无法处理/TASK2的请求,直到这些同步函数执行完毕,才会轮到/TASK2运行,所以导致/TASK2延迟。
解决方案
要让两个命令并行执行,核心是不让同步阻塞函数占用事件循环,可以通过以下两种方式实现:
方式1:将同步函数改为异步函数(推荐)
如果first_def、second_def、task2_def1等函数是你自己编写的,优先把它们改成异步版本,用async def定义,内部IO操作(比如网络请求、文件读写)替换为异步实现,然后在命令处理函数里用await调用:
# 把同步函数改为异步示例 async def first_def(): # 原同步逻辑替换为异步操作,比如用aiohttp代替requests,asyncio.sleep代替time.sleep await asyncio.sleep(10) async def cmd_TASK1(client,message): await first_def() first_step = await message.reply_text("First Step Done .",message.id) await second_def() second_step = await bot.edit_message_text(message.chat.id,first_step.id,"Second Step Done.") await third_def() third_step = await bot.edit_message_text(message.chat.id,second_step.id,"Third Step Done.") await bot.edit_message_text(message.chat.id,third_step.id,"All Step Done.")
方式2:用线程池/进程池运行同步函数
如果无法修改同步函数(比如是第三方库的函数),可以用asyncio的run_in_executor把同步函数放到线程池或进程池里执行,避免阻塞事件循环:
修改后的完整代码
import asyncio from concurrent.futures import ThreadPoolExecutor from pyrogram import Client, compose,filters from defs import * # 创建线程池,根据并发需求调整worker数量 executor = ThreadPoolExecutor(max_workers=4) async def main(): user = Client(user_detail) bot = Client(bot_detail) clients = [user, bot] # 获取当前事件循环 loop = asyncio.get_event_loop() # 第一个命令TASK1执行耗时30秒 @bot.on_message(filters.command("TASK1", [".","/"])) async def cmd_TASK1(client,message): # 用线程池执行同步函数,不阻塞事件循环 await loop.run_in_executor(executor, first_def) first_step = await message.reply_text("First Step Done .",message.id) await loop.run_in_executor(executor, second_def) second_step = await bot.edit_message_text(message.chat.id,first_step.id,"Second Step Done.") await loop.run_in_executor(executor, third_def) third_step = await bot.edit_message_text(message.chat.id,second_step.id,"Third Step Done.") await bot.edit_message_text(message.chat.id,third_step.id,"All Step Done.") # 第二个命令TASK2执行耗时5秒 @bot.on_message(filters.command("TASK2", [".","/"])) async def cmd_TASK2(client,message): await loop.run_in_executor(executor, task2_def1) first_step = await message.reply_text("50% Done.",message.id) await loop.run_in_executor(executor, task2_def2) await bot.edit_message_text(message.chat.id,first_step.id,"All Done Successfully") await compose(clients) asyncio.run(main())
关键说明
- 线程池适合IO密集型任务(比如网络请求、文件读写);如果是CPU密集型任务,可换成
ProcessPoolExecutor,但进程池开销更大,需注意资源占用。 max_workers可根据你的并发量调整,一般设置为CPU核心数或稍高。- 不要在同步函数里调用Pyrogram的API方法(如
message.reply_text),这些必须在异步函数中用await执行。
内容的提问来源于stack exchange,提问作者Mainul
相关产品推荐
相关产品推荐

