Discord音乐机器人报错:RuntimeWarning: coroutine 'autoplay'未被等待
Discord音乐机器人报错修复方案
出现的报错
- Task was destroyed but it is pending!
任务信息:<Task pending name='Task-21' coro=<autoplay() running at c:\Users\S1ncer3ly\Desktop\DiscordMusicBot-main\main.py:38>> - RuntimeWarning: coroutine 'autoplay' was never awaited
问题根源
两个报错都和autoplay协程的生命周期管理不当有关:
- 断开机器人时,
is_playing被设为False,但autoplay循环中的await asyncio.sleep(.5)仍处于挂起状态,导致任务被销毁时未完成。 - 用
loop.create_task创建任务后没有跟踪引用,也未在退出时等待任务结束,引发协程未被妥善等待的警告。
修复步骤
1. 跟踪autoplay任务引用
在全局变量区域添加变量保存任务引用:
# 全局变量部分添加 autoplay_task = None
修改summon命令,使用asyncio.create_task创建任务并保存:
@bot.command(pass_context=True, name='summon', help='Connect the bot to voice channel') async def summon(ctx): global is_playing, autoplay_task if not await check_if_user_connected(ctx): return voice = get(bot.voice_clients, guild=ctx.guild) if voice: await ctx.channel.send('Bot is already connected to voice channel') return is_playing = True channel = ctx.author.voice.channel await channel.connect() autoplay_task = asyncio.create_task(autoplay(ctx)) await ctx.channel.send( f"Connected to {channel}, Playing in {'Recommendation' if is_recommended else 'Auto Playlist'} mode.")
修改disconnect命令,等待任务完成后再断开:
@bot.command(pass_context=True, name='disconnect', help='Disconnect the bot') async def disconnect(ctx): global is_playing, autoplay_task voice = await get_bot_voice(ctx) if not voice: return is_playing = False if autoplay_task is not None: await autoplay_task autoplay_task = None await ctx.channel.send('Bye Bye') await voice.disconnect()
2. 优化autoplay循环退出逻辑
修改autoplay函数,确保is_playing为False时能快速退出:
async def autoplay(ctx): global is_skipping, current_playing_song, current_song_data while is_playing: if playlist: voice = get(bot.voice_clients, guild=ctx.guild) # 检查语音连接状态,防止断开后报错 if not voice or not voice.is_connected(): break current_song_data = playlist.pop() current_playing_song = current_song_data[0] await ctx.channel.send('Now playing ' + current_song_data[1]) with youtube_dl.YoutubeDL({}) as ydl: video = ydl.extract_info(current_song_data[1], download=False) await bot.change_presence(activity=discord.Streaming(name=video['title'], url=current_song_data[1])) voice.play(discord.FFmpegPCMAudio(f'audio_cache/{current_song_data[0]}.webm')) # 内层循环增加is_playing判断,确保能及时退出 while is_playing and (voice.is_playing() or voice.is_paused()): if is_skipping: is_skipping = False voice.stop() break else: await asyncio.sleep(.5) else: # 空列表时先检查是否要退出 if not is_playing: break if is_repeat_mode: playlist.append(current_song_data) elif is_recommended: video_id = current_playing_song if current_playing_song else get_random_song()[-1] await get_recommended_song(ctx, video_id) else: audio = get_random_song() await download_file(ctx.channel, audio[0], audio[1])
3. 删除多余的事件循环引用
删除全局变量中的loop = asyncio.get_event_loop(),直接使用asyncio.create_task即可,Discord.py会自动管理事件循环。
内容的提问来源于stack exchange,提问作者siddharth chaudhary
相关产品推荐
相关产品推荐

