Python如何暂停函数执行其他任务 解决Telegram bot消息阻塞问题
问题原因
你遇到的阻塞问题根源是do_with_file是同步长耗时函数,aiogram基于asyncio单线程事件循环运行,同步任务执行时会完全卡住事件循环,导致后续所有用户请求都无法被响应,没有办法直接“暂停”同步函数的执行,你需要把长耗时任务从主事件循环中剥离。
可行解决方案
方案:使用线程池运行同步阻塞任务
asyncio内置了run_in_executor方法,可以把同步函数扔到独立线程池运行,不会阻塞主事件循环处理其他用户请求。同时你需要修改固定文件名的逻辑,避免多用户上传时文件覆盖。如果需要控制同时处理的文件任务上限,还可以自定义线程池限制并发数。
修改后代码示例
import asyncio import os from concurrent.futures import ThreadPoolExecutor from aiogram import Dispatcher, types from aiogram.types import ContentTypes from aiogram.utils import executor dp = Dispatcher(bot) # 自定义线程池,最多同时处理2个文件任务,可根据服务器配置调整 file_executor = ThreadPoolExecutor(max_workers=2) @dp.message_handler(commands=["start"]) async def messages(mes: types.Message): if mes.text == "Hi": await bot.send_message(chat_id=mes.chat.id, text="Hi") if mes.text == "/start": await bot.send_document(mes.from_user.id, document=input_file.InputFile("c.pdf")) # 原有同步文件处理函数无需修改 def do_with_file(file_path: str): # 此处保留你原有的长耗时处理逻辑 pass @dp.message_handler(content_types=ContentTypes.DOCUMENT) async def doc_handler(message: types.Message): if document := message.document: # 生成唯一文件名,避免多用户上传时文件互相覆盖 file_path = f"{message.from_user.id}_{document.file_id}.pdf" await document.download(destination_file=file_path) await bot.send_message(chat_id=message.chat.id, text="文件已接收,后台处理中,完成后将通知你") # 将同步任务扔到独立线程池运行,不阻塞主事件循环 loop = asyncio.get_event_loop() await loop.run_in_executor(file_executor, do_with_file, file_path) # 处理完成后给用户发送通知 await bot.send_message(chat_id=message.chat.id, text="文件处理完成") # 可选:处理完成后删除本地临时文件 os.remove(file_path) if __name__ == '__main__': executor.start_polling(dp, skip_updates=True)
额外优化建议
- 如果你的文件处理逻辑支持异步实现,直接改成异步函数用await调用即可,不需要引入线程池
- 若有大流量高并发处理需求,可以单独搭建任务队列处理文件任务,适合分布式部署场景
内容的提问来源于stack exchange,提问作者No Name
相关产品推荐
相关产品推荐

