【问题标题】:Schedule Asyncio task to execute every X seconds?安排Asyncio任务每X秒执行一次?
【发布时间】:2019-06-06 18:40:01
【问题描述】:

我正在尝试创建一个 python discord 机器人,它将每 X 秒检查一次活跃成员,并根据他们的在线时间奖励成员。我正在使用 asyncio 来处理聊天命令,这一切正常。我的问题是找到一种方法来安排每隔 X 秒异步检查一次活动成员

我已经阅读了 asnycio 文档,但这是我第一次使用它,我很难将注意力集中在任务、循环和协同例程等方面。

@client.event
async def on_message(message):

    # !gamble command
    if message.content.startswith('!gamble'):

        ...code that works....

    # !help command
    elif message.content == '!help':

         ...code that works....

    # !balance command
    elif message.content == '!balance':

      ...code that works....

@client.event
async def on_ready():
    print('Logged in as')
    print(client.user.name)
    print(client.user.id)
    print('------')

# Do this every X seconds to give online users +1 points
async def periodic_task():
      TODO

我的目标是让机器人能够处理通过聊天发出的命令,同时每隔 X 秒触发一个与 Discord 服务器中的聊天命令或事件无关的功能。我知道如何使函数内的代码达到我的目标,只是不知道如何触发它

【问题讨论】:

    标签: python discord python-asyncio


    【解决方案1】:

    如果您想确保执行时间不会导致间隔漂移,您可以使用 asyncio.gather。

    import asyncio, time, random
    
    
    start_time = time.time()
    
    
    async def stuff():
        await asyncio.sleep(random.random() * 3)
        print(round(time.time() - start_time, 1), "Finished doing stuff")
    
    
    async def do_stuff_periodically(interval, periodic_function):
        while True:
            print(round(time.time() - start_time, 1), "Starting periodic function")
            await asyncio.gather(
                asyncio.sleep(interval),
                periodic_function(),
            )
    
    
    asyncio.run(do_stuff_periodically(5, stuff))
    

    然后输出变成:

    0.0 Starting periodic function
    0.5 Finished doing stuff
    5.0 Starting periodic function
    7.2 Finished doing stuff
    10.0 Starting periodic function
    10.1 Finished doing stuff
    15.0 Starting periodic function
    17.9 Finished doing stuff
    

    如您所见,调用的周期性函数的执行时间不会影响新间隔的开始时间。

    【讨论】:

    • 我如何让do_stuff_periodically 稍后停止?
    • 有什么办法可以避免它仍然存在的小漂移吗?它在这里的每个周期都会损失几毫秒
    • @filippo 你确定有实际漂移并且测量准确吗?
    【解决方案2】:
    async def do_stuff_every_x_seconds(timeout, stuff):
        while True:
            await asyncio.sleep(timeout)
            await stuff()
    

    并将其添加到循环中。

    task = asyncio.create_task(do_stuff_every_x_seconds(10, stuff))
    

    当你不想再这样做时,

    task.cancel()
    

    【讨论】:

    • 伙计们,请注意此解决方案仅适用于 python >3.7
    • 这会随着stuff 和sleep 顺序运行而漂移,@marcoc88 中使用asyncio.gather 的解决方案似乎是诀窍
    猜你喜欢
    • 2021-12-18
    • 2012-02-05
    • 1970-01-01
    • 2019-03-09
    • 1970-01-01
    • 1970-01-01
    • 2018-12-14
    • 1970-01-01
    • 2011-09-04
    相关资源
    最近更新 更多