【问题标题】:Python 3 with asyncio tasks not executed when returned in a generator function在生成器函数中返回时未执行异步任务的 Python 3
【发布时间】:2019-11-27 10:20:31
【问题描述】:

第一个示例不起作用,我尝试发出异步任务,但不关心这种情况下的响应,输出为空:

from typing import Iterable
import asyncio

async def example_task():
    print('example_task')

def emit() -> Iterable:
    event_loop = asyncio.get_event_loop()
    yield event_loop.create_task(example_task())

async def main():
    emit()
    await asyncio.sleep(0.5) # wait some time so the task can run

asyncio.run(main())

当我添加next(emit()) 以实际“读取”产生的任务时,输出工作,并且在下一个示例中,当我首先将所有任务放入列表时它工作:

from typing import Iterable
import asyncio

async def example_task():
    print('example_task')

def emit() -> Iterable:
    event_loop = asyncio.get_event_loop()
    return iter([event_loop.create_task(example_task())]) 

async def main():
    emit()
    await asyncio.sleep(0.5) # wait some time so the task can run

asyncio.run(main())

这只是一个简单的例子,最终版本应该能够发出一个“事件”并运行 1..n 个可以返回值但不需要的异步任务。发出的调用者应该能够决定他是在某个时候等待结果还是像示例中那样忽略它。

有什么方法可以使用生成器/yield 来做到这一点,或者是将所有任务存储在列表中并在此之后返回迭代器的唯一可能方法?

【问题讨论】:

  • 为什么这很重要?我的意思是让出每个任务还​​是返回完整列表?
  • 如果你不推进一个生成器,它的代码none会执行。为什么你期望它在它从未实际运行时分派任务?
  • 我以为任务会在create_task 调用后立即运行,但我想我会收集所有任务并返回一个列表,谢谢!

标签: python-3.x python-asyncio


【解决方案1】:

问题是您正在返回带有第一个示例的生成器,而第二个示例具有需要执行的任务对象。

您的第一个示例的修改版本将类似于

async def main():
    next(emit())
    await asyncio.sleep(0.5) # wait some time so the task can run

async def main():
    for task in emit():
        await task
        await asyncio.sleep(0.5) # wait some time so the task can run

希望这能解释在创建任务时使用生成器和迭代器之间的区别。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-11
    • 2020-11-20
    • 2021-11-19
    相关资源
    最近更新 更多