如何让含阻塞操作的Python aiogram多用户Telegram Bot正常响应?
解决Telegram Bot单任务阻塞导致无响应的问题
问题根源
你的Bot在处理第一个用户请求时,后续用户无响应,核心原因是代码中的同步阻塞操作占用了aiogram的事件循环:
video.download()是同步下载逻辑,会一直占用线程直到下载完成subprocess.call()是同步调用ffmpeg,同样会阻塞线程直到剪辑结束
aiogram基于asyncio运行,事件循环被阻塞时无法处理新的用户请求,导致后续用户收不到任何响应。
正确实现方式
将所有同步阻塞操作异步化,通过线程池或异步子进程调用,让事件循环能同时处理多个请求。以下是修改后的完整代码:
import asyncio import subprocess from concurrent.futures import ThreadPoolExecutor from aiogram import Bot, Dispatcher, types from aiogram.utils import executor from pytube import YouTube import time API_TOKEN = 'tkn' bot = Bot(token=API_TOKEN) dp = Dispatcher(bot) video_folder = 'video/' # 创建线程池用于处理同步阻塞任务,max_workers可根据服务器配置调整 executor_pool = ThreadPoolExecutor(max_workers=4) @dp.message_handler() async def start_convert(message: types.Message): url = message.text yt = YouTube(url) await message.reply('accepted') video_name = time.strftime("%d-%m-%Y-%H-%M-%S") + '.mp4' video = yt.streams.get_highest_resolution() # 将同步的download操作放到线程池执行,避免阻塞事件循环 loop = asyncio.get_event_loop() await loop.run_in_executor(executor_pool, video.download, video_folder, video_name) await message.reply('downloaded') # 使用异步子进程调用ffmpeg,替代同步的subprocess.call process = await asyncio.create_subprocess_exec( 'ffmpeg', '-hide_banner', '-loglevel', 'error', '-i', f'{video_folder}{video_name}', '-ss', '0', '-c:v', 'libx264', '-c:a', 'aac', '-b:v', '5M', '-to', '60', f'{video_folder}1_min_{video_name}', stdout=subprocess.PIPE, stderr=subprocess.PIPE ) # 等待子进程执行完成 await process.communicate() await message.reply('trimmed') if __name__ == '__main__': executor.start_polling(dp, skip_updates=True)
核心修改说明
线程池处理同步下载:
用ThreadPoolExecutor创建线程池,通过loop.run_in_executor把video.download()放到独立线程中执行,事件循环可以继续处理其他用户的请求。异步调用ffmpeg:
替换subprocess.call()为asyncio.create_subprocess_exec()——这是asyncio原生的异步子进程API,不会阻塞事件循环,同时通过await process.communicate()等待剪辑任务完成。并发控制:
线程池的max_workers参数可以根据服务器CPU、带宽资源调整,避免同时启动过多下载/剪辑任务导致资源耗尽。
内容的提问来源于stack exchange,提问作者Tony Reznik
相关产品推荐
相关产品推荐

