Discord Python机器人-从未等待的协程

时间:2020-09-10 23:16:27

标签: python asynchronous async-await discord bots

我正在尝试使用Python进行盲人测试的机器人游戏,实际上效果还不错。通过该play_next()函数,我设法在队列中获得了一个完整的Spotify播放列表。

def play_next(ctx):

    if len(song_queue) >= 1:
        del song_queue[0]
        source = song_queue[0]
        vc.play(FFmpegPCMAudio(source=source.preview_url),
            after=lambda e: play_next(ctx))
        track_played = source

@client.command()
async def start(ctx):
    ...
    ...
    for song in tracks:
        if not song.track.preview_url:
            continue
        source = song.track
        song_queue.append(source)
        if not vc.is_playing():
            vc.play(FFmpegPCMAudio(source=source.preview_url),
                after=lambda e: play_next(ctx))
            track_played = source

同样,先前的代码运行良好,但是一旦我将play_next()功能转到async以输出有关正在播放的曲目的详细信息,问题就会开始。

async def play_next(ctx):

    await ctx.send("The answer was: {} from {}".format(track_played.name,
        ' and'.join(track_played.artists)))
    if len(song_queue) >= 1:
        del song_queue[0]
        source = song_queue[0]
        await ctx.send('Next song is about to start')
        vc.play(FFmpegPCMAudio(source=source.preview_url),
            after=lambda e: play_next(ctx))
        track_played = source

运行前面的代码会引发以下错误:play_next() was never awaited。 现在我知道很多人都经历过这种类型的问题,但是我似乎似乎无法理解最近几个小时所读的内容,而我尝试过的任何方法都无法解决此问题……如果有人可以启发我,那太好了!

编辑

我终于遇到了一个解决方案,老实说,我不知道这是安全的还是好的做法。 我必须使该play_next()函数保持同步,并在另一个ctx.send()函数中获得对async的调用,如下所示:

async def sendMsg(message, ctx):
    await ctx.send(message)

并使用asyncio在主循环线程中调用协程。参见:

def play_next(ctx):
    ...
    send_fut = asyncio.run_coroutine_threadsafe(sendMsg(message, ctx), loop)
    send_fut.result()
    if len(song_queue) >= 1:
        source = song_queue[0]
        message = ('Next song is about to start')
        send_fut = asyncio.run_coroutine_threadsafe(sendMsg(message, ctx), loop)
        send_fut.result()
        del song_queue[0]
        track_played = source
        vc.play(FFmpegPCMAudio(source=source.preview_url),
                after=lambda x: play_next(ctx))

先前在loop中用全局变量初始化了main()。请注意,在找到正确的命令和位置之前,我尝试了很多命令和位置,这使我在这两条线上非常费劲。请注意get_event_loop()而不是new_event_loop()

def main():
    global loop

    loop = asyncio.get_event_loop()
    asyncio.set_event_loop(loop)
    def_globals()
    client.run('TOKEN')

希望这可能现在对其他人有所帮助!

0 个答案:

没有答案