【问题标题】:Break loop on new command在新命令上中断循环
【发布时间】:2022-01-12 13:50:01
【问题描述】:

我有一个不和谐的机器人来控制一些 RGB 灯。我想要一个重复的模式。但是,我需要在键入任何新命令后立即中断循环。

@client.command()
async def rainbow(ctx):
    await ctx.send("It is rainbow")
    while True:
     rainbow_cycle(0.001)

我知道虽然真正的循环不能被打破,但我不知道循环这个函数的另一种方法。如果这里需要完整的代码是Github链接https://github.com/MichaelMediaGroup/Discord_controlled_lights/blob/main/discord/main.py

感谢您的帮助

【问题讨论】:

  • 您想通过输入同一用户甚至其他人的另一个命令来打破循环吗?
  • while 循环和rainbow_cycle阻塞。在此过程中,您的机器人甚至无法处理其他命令,更不用说与它们交互了。可行的方法可能是将您的彩虹循环定义为task 并让您的彩虹命令启动任务循环,而所有其他命令在它处于活动状态时将其停止(最好通过pre-invoke hook

标签: python-3.x discord discord.py


【解决方案1】:

这不是我认为的最佳选择,但应该可以:

您可以为循环创建一个新的全局值,如下所示:

loop = False;

@client.command()
async def rainbow(ctx):
    await ctx.send("It is rainbow")
    global loop
    loop = True
    while loop:
        rainbow_cycle(0.001)


@client.command()
async def anothercommand(ctx):
    global loop
    loop = False
    #Some other stuff here

【讨论】:

  • 虽然这会将循环的控制转移到全局范围内,但命令中仍然存在完全阻塞while True 循环的巨大问题。仅此一项就可以防止机器人在彩虹运行时处理任何其他命令。如果要使用阻塞while循环,它绝对需要在单独的线程中运行
  • 我同意,他将无法使用其他命令。我的错。
【解决方案2】:

在此处创建while 循环可能不是最佳做法。而是使用您正在使用的不和谐模块中的tasks.loop()。 请注意,这必须从discord.ext 手动导入 所以它看起来像这样:

from discord.ext import commands, tasks

@bot.command
async def rainbow(ctx):
    await ctx.send("It is rainbow")
    if rainbow_.is_running():
        rainbow_.stop()
    else:
        rainbow_.start()

@tasks.loop(seconds=0)
async def rainbow_():
    # Do your things here
    rainbow_cycle(0.001)

现在我们已经创建了一个非阻塞循环,这个循环可以通过你的命令来启动/停止。

请注意

1] 不要在任务中使用像 sleep 这样的阻塞命令(如果你想休眠,请改用 asyncio.sleep(foo)

2] 不要在on_ready 下启动rainbow_,因为on_ready 会被多次调用并且会创建不必要的实例,但是如果您确实想在准备就绪时启动任务,请确保它尚未运行首先。

【讨论】:

    猜你喜欢
    • 2018-01-31
    • 2014-03-08
    • 2019-09-29
    • 2018-09-16
    • 2011-12-27
    • 2022-01-14
    • 2013-08-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多