【问题标题】:python how to make early return when asyncio generatorpython如何在异步生成器时提前返回
【发布时间】:2021-11-19 09:55:33
【问题描述】:

我想返回异步生成器的第一个元素并处理剩余的值,而不是像火和忘记一样返回。如何让python中的协程提前返回? 将迭代器传递给asyncio.create_task 后,它不会打印剩余的值。

import asyncio
import time


async def async_iter(num):
    for i in range(num):
        await asyncio.sleep(0.5)
        yield i

async def handle_remains(it):
    async for i in it:
        print(i)

async def run() -> None:
    it = async_iter(10)
    async for i in it:
        print(i)
        break
    # await handle_remains(it) 
    # want to make this `fire and forget`(no await), expecting just printing the remainning values.
    asyncio.create_task(handle_remains(it))
    return i

if __name__ == '__main__':
    asyncio.run(run())
    time.sleep(10)

【问题讨论】:

  • 你需要有一个运行任务的事件循环:看看documentation
  • @Jens 这不是asyncio.run() 为你做的吗?
  • create_task() 函数返回一个 Task 在示例代码中被丢弃——即未分配并按计划进行。
  • @Jens 嗯,来自链接:任务在 get_running_loop() 返回的循环中执行,如果当前线程中没有运行循环,则会引发 RuntimeError。
  • @Jens 也许我误解了这句话,它只是关于任务在哪个循环中执行,而不是关于执行本身?不过,读起来有点矛盾。

标签: python generator python-asyncio


【解决方案1】:

你已经接近了代码,但还没有完成(另见我上面的 cmets)。简而言之,创建Task 是不够的:任务需要运行:

task = asyncio.create_task(handle_remains(it))  # Creates a Task in `pending` state.
await task  # Run the task, i.e. execute the wrapped coroutine.

一个任务,连同协程和期货,是一个“Awaitable”。事实上:

当使用 asyncio.create_task() 之类的函数将协程包装到 Task 中时,协程会自动安排为很快运行。

注意“计划很快运行”,现在您必须通过调用 await 来确保实际运行任务,关键字...

用于获取协程执行的结果。

【讨论】:

  • 但是如果您不想明确地await 任务怎么办?例如。在 Node.js 中,事件循环一直运行,直到没有更多任务要运行。
  • @Jens 我不想等待任务。只想像js事件循环一样触发并忘记。但现在我明白了create_task,谢谢!
  • 嗯,这是 Python 而不是 JavaScript——不同的语言,不同的运行时。您是否介意分享上面 Python 示例的 JavaScript 等效项(例如 Gist),以说明您希望在这里实现什么?
猜你喜欢
  • 2010-12-20
  • 2017-05-12
  • 1970-01-01
  • 1970-01-01
  • 2019-11-16
  • 2019-04-12
  • 1970-01-01
  • 2019-02-25
  • 2015-01-05
相关资源
最近更新 更多