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

如何让含阻塞操作的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)

核心修改说明

  1. 线程池处理同步下载:
    用ThreadPoolExecutor创建线程池,通过loop.run_in_executor把video.download()放到独立线程中执行,事件循环可以继续处理其他用户的请求。

  2. 异步调用ffmpeg:
    替换subprocess.call()为asyncio.create_subprocess_exec()——这是asyncio原生的异步子进程API,不会阻塞事件循环,同时通过await process.communicate()等待剪辑任务完成。

  3. 并发控制:
    线程池的max_workers参数可以根据服务器CPU、带宽资源调整,避免同时启动过多下载/剪辑任务导致资源耗尽。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 00:21:26