在异步事件循环中制作简单加载图标的问题
Issues with making a simple loading icon inside an async event loop
我正在为 discord 服务器制作一个机器人,并且有一个功能需要一些时间才能 运行。我想像这样 Doing something: <spinning icon>
在状态消息旁边添加一个旋转加载图标。它编辑原始消息以遍历这些消息:
Doing something: \
Doing something: |
Doing something: /
Doing something: -
我尝试使用单独的线程来更新消息,如下所示:
async def loadingBar(ctx, message : discord.Message):
loadingMessage0 = "{0}: \".format(message)
loadingMessage1 = "{0}: |".format(message)
loadingMessage2 = "{0}: /".format(message)
loadingMessage3 = "{0}: -".format(message)
index = 0
while True:
if(index == 0):
await message.edit(contents = loadingMessage0)
index = 1
elif(index == 1):
await message.edit(contents = loadingMessage1)
index = 2
elif(index == 2):
await message.edit(contents = loadingMessage2)
index = 3
elif(index == 1):
await message.edit(contents = loadingMessage1)
index = 0
再往下,启动进程的 bot 命令...
@bot.command()
async def downloadSong(ctx, url : str, songname : str):
#Other code that doesn't matter
message = await ctx.send("Downloading audio")
_thread = threading.Thread(target=asyncio.run, args=(loadingBar(ctx, message),))
_thread.start()
#Function that takes a while
#Some way to kill thread, never got this far
但是,我收到错误 Task <Task pending coro=<loadingBar() running at bot.py:20> cb=[_run_until_complete_cb() at /Users/user/.pyenv/versions/3.7.3/lib/python3.7/asyncio/base_events.py:158]> got Future <Future pending> attached to a different loop
。我是异步编程和不和谐库的新手;有没有更好的方法来做到这一点,如果没有,我做错了什么?
首先,您应该在 while 循环内的迭代之间添加一个延迟,为此使用 asyncio.sleep
。
其次 - asyncio 和线程并不能真正协同工作,这里使用线程也没有意义,因为它违背了 asyncio 的全部目的,使用 asyncio.create_task
到 运行 协程“在背景”,你可以把它赋值给一个变量,然后调用cancel
方法停止任务。
import asyncio
async def loadingBar(ctx, message : discord.Message):
loadingMessage0 = "{0}: \".format(message)
loadingMessage1 = "{0}: |".format(message)
loadingMessage2 = "{0}: /".format(message)
loadingMessage3 = "{0}: -".format(message)
index = 0
while True:
if(index == 0):
await message.edit(contents = loadingMessage0)
index = 1
elif(index == 1):
await message.edit(contents = loadingMessage1)
index = 2
elif(index == 2):
await message.edit(contents = loadingMessage2)
index = 3
elif(index == 1):
await message.edit(contents = loadingMessage1)
index = 0
await asyncio.sleep(1) # you can edit the message 5 times per 5 seconds
@bot.command()
async def downloadSong(ctx, url : str, songname : str):
message = await ctx.send("Downloading audio")
task = asyncio.create_task(loadingBar(ctx, message)) # starting the coroutine "in the background"
# Function that takes a while
task.cancel() # stopping the background task
我正在为 discord 服务器制作一个机器人,并且有一个功能需要一些时间才能 运行。我想像这样 Doing something: <spinning icon>
在状态消息旁边添加一个旋转加载图标。它编辑原始消息以遍历这些消息:
Doing something: \
Doing something: |
Doing something: /
Doing something: -
我尝试使用单独的线程来更新消息,如下所示:
async def loadingBar(ctx, message : discord.Message):
loadingMessage0 = "{0}: \".format(message)
loadingMessage1 = "{0}: |".format(message)
loadingMessage2 = "{0}: /".format(message)
loadingMessage3 = "{0}: -".format(message)
index = 0
while True:
if(index == 0):
await message.edit(contents = loadingMessage0)
index = 1
elif(index == 1):
await message.edit(contents = loadingMessage1)
index = 2
elif(index == 2):
await message.edit(contents = loadingMessage2)
index = 3
elif(index == 1):
await message.edit(contents = loadingMessage1)
index = 0
再往下,启动进程的 bot 命令...
@bot.command()
async def downloadSong(ctx, url : str, songname : str):
#Other code that doesn't matter
message = await ctx.send("Downloading audio")
_thread = threading.Thread(target=asyncio.run, args=(loadingBar(ctx, message),))
_thread.start()
#Function that takes a while
#Some way to kill thread, never got this far
但是,我收到错误 Task <Task pending coro=<loadingBar() running at bot.py:20> cb=[_run_until_complete_cb() at /Users/user/.pyenv/versions/3.7.3/lib/python3.7/asyncio/base_events.py:158]> got Future <Future pending> attached to a different loop
。我是异步编程和不和谐库的新手;有没有更好的方法来做到这一点,如果没有,我做错了什么?
首先,您应该在 while 循环内的迭代之间添加一个延迟,为此使用 asyncio.sleep
。
其次 - asyncio 和线程并不能真正协同工作,这里使用线程也没有意义,因为它违背了 asyncio 的全部目的,使用 asyncio.create_task
到 运行 协程“在背景”,你可以把它赋值给一个变量,然后调用cancel
方法停止任务。
import asyncio
async def loadingBar(ctx, message : discord.Message):
loadingMessage0 = "{0}: \".format(message)
loadingMessage1 = "{0}: |".format(message)
loadingMessage2 = "{0}: /".format(message)
loadingMessage3 = "{0}: -".format(message)
index = 0
while True:
if(index == 0):
await message.edit(contents = loadingMessage0)
index = 1
elif(index == 1):
await message.edit(contents = loadingMessage1)
index = 2
elif(index == 2):
await message.edit(contents = loadingMessage2)
index = 3
elif(index == 1):
await message.edit(contents = loadingMessage1)
index = 0
await asyncio.sleep(1) # you can edit the message 5 times per 5 seconds
@bot.command()
async def downloadSong(ctx, url : str, songname : str):
message = await ctx.send("Downloading audio")
task = asyncio.create_task(loadingBar(ctx, message)) # starting the coroutine "in the background"
# Function that takes a while
task.cancel() # stopping the background task