【问题标题】:Discord py create a new tasks.loop object for each loopDiscord py 为每个循环创建一个新的 tasks.loop 对象
【发布时间】:2021-02-08 20:05:35
【问题描述】:

我正在尝试使用 Discord 机器人多次运行 task.loop,但是由于循环已经在运行,因此这不起作用。

我在another question找到了这个答案:

async def loop(name):
    print(name)

names = ["Jon", "Joseph"]

loops = {name: tasks.loop(seconds=10)(name) for name in names}

但是,我想不通。 我不明白如何自动创建一个新循环,这个程序总是出现这个错误:

Traceback (most recent call last):
  File "main.py", line 11, in <module>
    loops = {name: tasks.loop(seconds=10)(name) for name in names}
  File "main.py", line 11, in <dictcomp>
    loops = {name: tasks.loop(seconds=10)(name) for name in names}
  File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/tasks/__init__.py", line 506, in decorator
    return Loop(func, **kwargs)
  File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/tasks/__init__.py", line 76, in __init__
    raise TypeError('Expected coroutine function, not {0.__name__!r}.'.format(type(self.coro)))
TypeError: Expected coroutine function, not 'str'.

我复制了代码试一试,然后粘贴到一个新程序中,现在看起来像这样:

import discord
from discord.ext import tasks

async def loop(name):
    print(name)

names = ["Jon", "Joseph"]

loops = {name: tasks.loop(seconds=10)(name) for name in names}#What exactly does this line do?

我必须改变什么才能让这个错误消失并且循环可以多次执行?

【问题讨论】:

  • 伙计们,按 -1 然后甚至没有解释为什么在评论中根本没有帮助。

标签: python-3.x discord.py


【解决方案1】:

如果您不了解装饰器的基础知识,这有点难以解释,请查看this gigantic answer,它希望能为您解决一些问题。

我能给出的最短解释是装饰器将你的函数包装在另一个返回函数的函数中。您当前正在做的是用装饰器包装 STRING 而不是函数。

async def loop(name):
    print(name)

names = ["Jon", "Joseph"]
                                 # `loop` is the coroutine we defined above
loops = {name: tasks.loop(seconds=10)(loop) for name in names}
# Note that this is just a dict that holds functions, to start it
for name, coro in loops.items():
    coro.start(name)

如果你想直接在字典理解中开始循环

loops = {name: tasks.loop(seconds=10)(loop).start(name) for name in names}

如果你可以简单地做,我不确定你为什么要做这样的事情:

names = ["Jon", "Joseph"]

@tasks.loop(seconds=10)
async def loop():
    for name in names:
        print(name)


loop.start()

【讨论】:

  • 谢谢,我不得不在另一个答案中给你间接问题的答案。你的回答对我帮助很大
【解决方案2】:

@Łukasz Kwieciński - 我必须这样回答你,因为答案太长了

这只是一个例子, 我在我的主脚本中定义了一个应该被多次调用的循环:

@tasks.loop(minutes=1)
async def AutoRole(ctx, guild:discord.guild, role:discord.Role, members:discord.Member, startTime:int, endTime:int):
  if (datetime.datetime.now().hour+1 >= startTime) and (datetime.datetime.now().hour+1 < endTime):
    for memberID in members:
      member = guild.get_member(memberID)
      await member.add_roles(role)
  else:
    for memberID in members:
      member = guild.get_member(memberID)
      await member.remove_roles(role)

我这样称呼它:

@bot.command()
async def startAR(ctx, role:discord.Role)
  if ctx.message.author.guild_permissions.administrator:
    startTime = X #I retrieve this data from a database
    endTime = Y #I retrieve this data from a database
    members = Z #I retrieve this data from a database
    AutoRole.start(ctx, ctx.guild, role, members, startTime, endTime)
    echo.info(ctx, "Startet AutoRole " + role.name)
  else:
    await echo.warning(ctx, "You need Admin Role to edit roles")

由于您可以创建多个 AutoRoles,因此必须再次调用此循环,并提供不同的值。

但是对于测试,你的答案很好,它对我有帮助:

async def loop(name):
    print(name)

names = ["Jon", "Joseph"]
                                 # `loop` is the coroutine we defined above
loops = {name: tasks.loop(seconds=10)(loop) for name in names}
# Note that this is just a dict that holds functions, to start it
for name, coro in loops.items():
    coro.start(name)

【讨论】:

    猜你喜欢
    • 2015-06-29
    • 2020-10-07
    • 2011-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多