当我在不和谐中键入命令!sleeper
时,然后紧接着键入!hello
。机器人基本上处于暂停10秒,因为它正在处理!sleeper
。在10秒之后,它发送消息I have been sleeping for 10 seconds
,然后紧接着发送Hello partner!
。如果有人发送!sleeper
命令,我如何才能使整个机器人不被“暂停”。
现在发生了什么:
!sleeper
!hello
I have been sleeping for 10 seconds
Hello partner!
我想要的:
!sleeper
!hello
Hello partner!
I have been sleeping for 10 seconds
PS:我写了“等待9-10秒”,因为输入!hello
需要大约一秒钟的时间。
import time
from discord.ext import commands
class Hello(commands.Cog):
def __init__(self, client):
self.client = client
@commands.Cog.listener()
async def on_ready(self):
print(f'{self.__class__.__name__} Cog is ready')
@commands.command()
async def hello(self, ctx):
await ctx.send('Hello partner!')
@commands.command()
async def sleeper(self, ctx):
await self.sleep_now()
await ctx.send('I have been sleeping for 10 seconds')
async def sleep_now(self):
time.sleep(10)
def setup(client):
client.add_cog(Hello(client))
发布于 2021-11-21 12:11:30
根据您对凯尔答案的评论,您希望异步处理一个函数。
那么,您要实现的是一个线程。您可以创建一个线程并在线程内睡眠10秒(或者执行您的时间开销很大的任务),然后打印“我已经睡了10秒了”。因此,它不会阻止执行!hello和其他命令。它看起来会像这样
这将是昂贵的任务的功能。
async def thread_function(ctx):
time.sleep(10)
await ctx.send('I have been sleeping for 10 seconds')
你会这样称呼它
x = threading.Thread(target= thread_function, args=(ctx))
或者,您可以使用一个事件循环,这是一个更高级的主题。如果需要,您可以研究它,但是它实际上是计算运行时调用的函数,并独立执行它,而不创建新线程。我强烈鼓励你去看看。尽管如此,这是它可能的样子。
from concurrent.futures import ThreadPoolExecutor
loop = asyncio.get_event_loop()
_executor = ThreadPoolExecutor(1)
await loop.run_in_executor(_executor, thread_function, ctx)
发布于 2021-11-20 07:34:24
您可以尝试使用后台任务来实现这一点。我不确定这是最好的还是最干净的解决方案,但是您可以找到更多的文档这里。
from discord.ext import tasks, commands
class Hello(commands.Cog):
def __init__(self, client):
self.client = client
# flag variable to keep track of if we are waiting for a response from sleeper
self.sleeping = 0
@commands.Cog.listener()
async def on_ready(self):
print(f'{self.__class__.__name__} Cog is ready')
@commands.command()
async def hello(self, ctx):
await ctx.send('Hello partner!')
@commands.command()
async def sleeper(self, ctx):
# if the task is already running, ie. someone already called sleeper
# you cannot start a background task if it is already running, it will cause an error
if self.sleep.is_running():
await ctx.send('Already sleeping!')
else:
# start the background task
self.sleep.start(ctx)
# The loop runs 2 times
# It runs immediately when you start the task (when you type !sleeper) and then again in increments of the time specified
# I use a flag to check when to send the message and cancel the task (after the first ten seconds)
# cancelling the task stops it from sending additional messages every ten seconds
@tasks.loop(seconds=10.0)
async def sleep(self, ctx):
# helper method to stop the background task right after it sends the message
async def stop_sleep():
self.sleep.cancel()
# checks to see if the task is sleeping or not
if self.sleeping == 1:
# reset the value
self.sleeping = 0
# send the message
await ctx.send('I have been sleeping for 10 seconds')
# stop the task
await stop_sleep()
else:
# keep track of it sleeping
self.sleeping = 1
def setup(client):
client.add_cog(Hello(client))
编辑:
有一个更好的方法来解决你的问题,而不用背景任务。使用异步而不是睡眠时间。
from discord.ext import commands
import asyncio
class Hello(commands.Cog):
def __init__(self, client):
self.client = client
@commands.Cog.listener()
async def on_ready(self):
print(f'{self.__class__.__name__} Cog is ready')
@commands.command()
async def hello(self, ctx):
await ctx.send('Hello partner!')
@commands.command()
async def sleeper(self, ctx):
await asyncio.sleep(10)
await ctx.send('I have been sleeping for 10 seconds')
https://stackoverflow.com/questions/70043360
复制相似问题