Discord机器人Lambda表达式中调用异步方法无法使用await的解决方案
解决Discord机器人异步
play_next方法在after回调中无法使用await的问题 你遇到的核心问题是:discord.py的voice_client.play()方法的after参数只接受同步函数,不能直接在lambda里用await调用异步方法,这会触发语法错误。另外你的原代码还有几处语法问题需要先修正。
具体解决步骤:
- 修复原代码语法错误:
await ctx.send和voice_client.play必须放在if self.queue的代码块内,否则队列为空时会出现filename未定义的错误;同时调整else的缩进,保证代码结构合法。 - 用同步包装函数调度异步任务:写一个同步的回调函数,在里面通过
asyncio.run_coroutine_threadsafe把异步的play_next提交到机器人的事件循环中执行——因为after回调运行在非异步线程,必须用这种方式安全触发异步方法。
修正后的完整代码:
import asyncio import discord async def play_next(self, voice_client, ctx): if self.queue: self.is_playing = True array = self.queue.pop(0) audio, filename = discord.FFmpegPCMAudio(array[0]), array[1] await ctx.send(f"Now playing: {filename}") # 定义同步的播放完成回调 def after_play(e): # 可选:处理播放过程中的错误 if e: print(f"播放出错: {e}") # 将异步的play_next提交到机器人事件循环执行 asyncio.run_coroutine_threadsafe(self.play_next(voice_client, ctx), self.bot.loop) voice_client.play(audio, after=after_play) else: self.is_playing = False
关键说明:
asyncio.run_coroutine_threadsafe的作用是在非异步线程环境中,把异步任务提交到指定的事件循环(这里是机器人的self.bot.loop),确保异步方法能被正确调度,避免线程安全问题。- 如果你用的是discord.py的
commands.Bot实例,self.bot.loop就是机器人的事件循环,直接引用即可。
内容的提问来源于stack exchange,提问作者Simant Singh
相关产品推荐
相关产品推荐

