使用discord.py的Discord机器人同步处理命令、全量处理完才统一回复问题问询
问题根因
代码中的pytube视频下载、mega文件上传、本地文件删除操作都是同步阻塞调用,哪怕放在async定义的函数内,执行这些阻塞逻辑时会直接卡住Discord机器人的整个事件循环,导致后续的用户请求、消息回复操作全部被挂起,直到当前所有阻塞逻辑执行完毕,才会批量处理堆积的事件,最终表现为全部请求处理完才统一回复所有用户。
修复方案
通过asyncio.to_thread把阻塞逻辑丢到独立线程运行,同时用asyncio.create_task将请求处理逻辑转为后台异步任务,不阻塞主事件循环接收新请求,每个请求处理完成后会立刻回复对应用户。
修改后的参考代码如下:
import asyncio # 保留你原有其他依赖的导入逻辑不变 if clean_content[0] == "!get": #Get complete video (!get link) try: yt = pytube.YouTube(clean_content[1]) if yt.length > time_limit: await message.channel.send(f"Length of given video exceeds {time_limit//60} minutes, which is currently unsupported.") return # 将请求处理转为后台任务,不阻塞主事件循环接收下一个用户的请求 asyncio.create_task(get_func(message, yt)) return except: await message.reply("Some error occured :(") return async def get_func(message,yt): try: # 用用户ID作为文件名,避免用户名含特殊字符导致路径读写错误 file_path = f"./videos/down_{message.author.id}" # 所有同步阻塞逻辑都通过to_thread丢到独立线程执行,不卡事件循环 await asyncio.to_thread( lambda: yt.streams.get_highest_resolution().download(output_path="./videos", filename=f"down_{message.author.id}") ) main_folder = await asyncio.to_thread(lambda: new_mega.find('discord_videos')) file = await asyncio.to_thread(lambda: new_mega.upload(file_path, main_folder[0])) os.remove(file_path) print(f"processed {message.author}") await message.reply(f"File is only valid for {delete_time//3600} hour(s), link : {new_mega.get_upload_link(file)}") except: await message.reply("Some error occured :(")
额外优化建议
- 可添加并发数控制,避免短时间内大量下载、上传请求占满服务器带宽
- 异常捕获逻辑可添加具体错误日志打印,方便快速定位下载、上传阶段的问题
- 大文件上传可添加进度提示,提升用户使用体验
内容的提问来源于stack exchange,提问作者Sumedh Zope
相关产品推荐
相关产品推荐

