如何在 Python asyncio 中收集任务垃圾?

How do I collect task garbages in Python asyncio?

抱歉英语不好,但我会尽力的。

考虑以下代码:

import asyncio
async def main():
    async def printA():
        await asyncio.sleep(1)
        print('a')
    # create a stream
    stream=...
    async for message in stream:
        pass
asyncio.run(main())

是的,printA还没有使用。

现在我想在看到来自流的某些类型的消息时调用 printA

如果我可以接受流等待 printA 完成继续,我可以这样写:

async for message in stream:
    if message=='printA':
        await printA()

但是我不会,所以我至少要写:

async def main():
    async def printA():
        await asyncio.sleep(1)
        print('a')
    # create a stream
    stream=...
    taskSet=set()
    async for message in stream:
        if message=='printA':
            taskSet.add(asyncio.create_task(printA()))
    await asyncio.gather(*taskSet)

但如果流足够长,taskSet 会变得非常大,即使许多 printA(s) 事实上已经完成。

所以我希望它们一完成就被删除。

以后不知道怎么写了

我可以在 printA 内删除该任务吗? printA()的执行不会早于调用create_task,但会不会晚于create_task returns?文档似乎并不能保证这一点。虽然我发现 some 说它是由当前实现保证的。

我不能简单地丢弃任务引用,对吗?正如 create_task 的文档所说:

Important: Save a reference to the result of this function, to avoid a task disappearing mid execution.

您可以直接在错误报告中找到答案,该错误报告涉及导致文档更新的“即发即弃”任务的相同问题“重要:保存参考...”

https://bugs.python.org/issue44665

我将复制自动删除任务的方法:

running_tasks = set()
# [...]
task = asyncio.create_task(some_background_function())
running_tasks.add(task)
task.add_done_callback(lambda t: running_tasks.remove(t))