首页 > 解决方案 > python asyncio函数add_done_callback不起作用

问题描述

我正在使用 Set() 在我的程序中执行速率限制功能。但是有一些奇怪的行为。

  1. 有一些残留物task_set是不应该发生的。我已经补充add_done_callback说,该任务将在完成后自行删除task_set

  2. 有时会抛出 KeyError。但我不知道为什么,中的任务task_set不应该被删除超过 1 次

我尝试了不同的方法(信号量,队列......)但它们都没有按预期工作......如果有人可以分享一些关于如何在异步编程中实现速率限制的代码片段,我将不胜感激

import asyncio


def main():
    async def task(acc_id):
        print(f"acc_id {acc_id} received the task")
        await asyncio.sleep(5)
        print(f"acc_id {acc_id} finished the task")

    async def loop_tasks():
        task_set = set()

        for acc_id in range(1000000):
            # pause when reached the limit
            while len(task_set) > 10:
                await asyncio.sleep(0)

            t = event_loop.create_task(task(acc_id))
            task_set.add(t)
            t.add_done_callback(lambda _: task_set.remove(t))

    event_loop = asyncio.get_event_loop()
    event_loop.run_until_complete(loop_tasks())


main()

标签: pythonpython-asyncio

解决方案


我查看了程序输出异常,发现t是相同的值。

对文档的回顾表明,当callback被调用时,Future 对象是它的唯一参数。

进行以下更改后,程序可以正常运行。

t.add_done_callback(lambda current_task: task_set.remove(current_task))

推荐阅读