我如何在非异步函数中使用Await ?



我正在做一个不和谐机器人,试图解决这个问题。我想知道如何在非异步函数中使用await,如果我可以在lambda行(代码的最后一行)中等待函数。

我试过用玩家变量做asyncio.run,我也试过asyncio.run_coroutine_threadsafe,它不起作用。

关于如何使它工作有什么想法吗?

代码:

def queue_check(self, ctx):
global queue_list
global loop
global playing

if loop is True:
queue_list.append(playing)
elif loop is False:
playing = ''
if ctx.channel.last_message.content == '$skip' or '$s':
return
song = queue_list.pop(0)
player = await YTDLSource.from_url(song, loop=self.client.loop, stream=True)

ctx.voice_client.play(player, after= queue_check(self,ctx))


@commands.command(aliases=['p'])
@commands.guild_only()
async def play(self, ctx, *, url):
global queue_list
global playing

if ctx.voice_client is None:
if ctx.author.voice:
await ctx.author.voice.channel.connect()
else:
return await ctx.send("> You are not connected to a voice channel.")

async with ctx.typing():

player = await YTDLSource.from_url(url, loop=self.client.loop, stream=True)
await ctx.send(f'> :musical_note: Now playing: **{player.title}** ')

playing = url

await ctx.voice_client.play(player, after=lambda e: queue_check(self,ctx))

需要import asyncio

要实际运行协程,asyncio提供了三个主要机制:

  • asyncio.run()函数运行顶级入口点" main() "函数(参见上面的例子)
  • 等待协同程序。将打印下面的代码片段"hello"后等待1秒,然后打印"world"后等待2秒:

示例

import asyncio
import time
async def say_after(delay, what):
await asyncio.sleep(delay)
print(what)
async def main():
print(f"started at {time.strftime('%X')}")
await say_after(1, 'hello')
await say_after(2, 'world')
print(f"finished at {time.strftime('%X')}")
asyncio.run(main())

started at 17:14:32
hello
world
finished at 17:14:34

细节

我也是异步编程的新手,今天深入研究了一下。因此,不能在非异步函数中使用await是一个非常严格的规则。

所以你不能这样做:

def foo(delay):
await asyncio.sleep(delay)

async必须与await配对。但是,您可以向事件循环添加任务。我只是想发送一条消息,所以我做了这样的事情:

def queue_check(self, ctx):
#some preceding code
#
#adding a function to the event loop
self.bot.loop.create_task(ctx.send("my message"))

当asyncio决定它有足够的资源时,它就发送该消息。然而,在你的情况下。因为你需要player就在那里,这可能不合适。

如果我可以建议一个替代方法,而不是把字符串放在队列中:

song = queue_list.pop(0) #im confident song is a string

为什么不排队YTDLSource对象呢?

async def Q(self, ctx, url):
"""Add songs to Queue"""
player = await YTDLSource.from_url(url)
queue_list.append(player)

如果您确实需要(尽管不推荐),您可以从同步方法运行异步方法,而与实际循环运行的事实无关:

try:
asyncio.get_running_loop().run_until_complete(async_method())
except RuntimeError:
asyncio.run(async_method())

最新更新