'Discord Python bot - Coroutine never awaited
I'm trying to make a Blind-test bot game in Python, which actually works pretty fine. I managed to get a whole spotify playlist in the queue with that play_next()
function.
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
As soon I turn the play_next()
function to async
to output details about the tracks being played, problems start.
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
Running the previous code throws me this error:
play_next() was never awaited
How can I solve this?
Solution 1:[1]
(Note: this answer was originally added in Revision 3 of the question.)
I finally came across a solution, which I honestly don't know if it's safe or if it is good practice.
I had to leave that play_next()
function synchronous, and get the calls to ctx.send()
in another async
function, as follows:
async def sendMsg(message, ctx):
await ctx.send(message)
and use asyncio to call the coroutine in the main loop thread. See:
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))
Having previously initialised loop
in the main()
with a global variable. Note that I struggled a lot with those two lines as I tried numerous orders and places before finding the right one. Alose note the get_event_loop()
instead of new_event_loop()
.
def main():
global loop
loop = asyncio.get_event_loop()
asyncio.set_event_loop(loop)
def_globals()
client.run('TOKEN')
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |