discord.py机器人并发阻塞:如何将调用的同步类重构为异步结构
问题原因
discord.py 基于 asyncio 异步事件循环运行,你在命令协程中调用的MyClass内部使用了同步阻塞的requests库发起HTTP请求,会卡住整个事件循环,导致其他命令无法被同时处理。另外原代码中MyClass使用类级别的可变属性作为默认值,多实例调用时会出现数据串扰的bug,也需要同步修复。
重构方案1:全异步改造(推荐)
性能最优,适配异步框架的原生逻辑
第一步:替换同步HTTP库,改造自定义类
import aiohttp class MyClass: def __init__(self, args): # 改为实例属性,避免多实例共享数据串扰 self.parameters = args self.final_data = [] self.website_data = "" self.my_session = None @classmethod async def create(cls, args): # 异步构造入口,规避__init__无法异步的限制 instance = cls(args) instance.my_session = aiohttp.ClientSession() try: # 按你原有逻辑生成目标请求url即可 url = instance.get_target_url() await instance.get_request(url) instance.handle_data() finally: # 用完关闭session避免资源泄漏 await instance.my_session.close() return instance async def get_request(self, url): # 异步发起HTTP请求 async with self.my_session.get(url) as r: self.website_data = await r.text() def handle_data(self): # 原有同步数据处理逻辑无需修改,CPU计算不会阻塞事件循环 # 这里保留你原有的处理逻辑,把结果赋值给c即可 c = "你原有逻辑生成的结果" self.final_data.append(c) def get_target_url(self): # 你原有生成请求url的逻辑放这里 return "https://example.com"
改造前需要先安装异步HTTP库:pip install aiohttp
第二步:修改Discord Bot命令逻辑
import discord from discord.ext import commands intents = discord.Intents.default() intents.members = True bot = commands.Bot(command_prefix='?', intents=intents) # 注意原代码这里少了括号,@bot.command()才是正确写法 @bot.command() async def my_command(ctx, *args): # 异步获取MyClass实例 my_instance = await MyClass.create(args) a = my_instance.final_data # 保留你原有对a处理得到b的逻辑 b = "处理后的最终结果" await ctx.send(b)
重构方案2:同步逻辑线程隔离(无需修改原有MyClass代码)
适合不想改动老类逻辑的场景,改造成本最低,性能比全异步方案稍差
import discord from discord.ext import commands import asyncio intents = discord.Intents.default() intents.members = True bot = commands.Bot(command_prefix='?', intents=intents) @bot.command() async def my_command(ctx, *args): # 把同步调用扔到独立线程运行,不阻塞事件循环 a = await asyncio.to_thread(lambda: MyClass(args).final_data) # 保留你原有对a处理得到b的逻辑 b = "处理后的最终结果" await ctx.send(b)
内容的提问来源于stack exchange,提问作者dsbap
相关产品推荐
相关产品推荐

