You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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协程的生命周期管理不当有关:

  1. 断开机器人时,is_playing被设为False,但autoplay循环中的await asyncio.sleep(.5)仍处于挂起状态,导致任务被销毁时未完成。
  2. 用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 05:40:21