【问题标题】:List of coroutines, wait until at least one yielded in Python协程列表,等到至少一个在 Python 中产生
【发布时间】:2020-05-11 00:10:15
【问题描述】:

我以前从未使用过协程,所以这个问题对你来说可能是微不足道的。我有几个yield一些值的生成器,如下:

@asyncio.coroutine
def generator_1():
    while True:
        # do something
        yield value_1

@asyncio.coroutine
def generator_2():
    while True:
        # do something
        yield value_2

我想等到其中至少有一个产生了一些东西,即我不需要所有的屈服值,只需要其中一个。目前,我已经按照我在网上找到的示例进行了以下操作:

async def get_at_least_one():
    await asyncio.wait(generator_1(), generator_2(), return_when=asyncio.FIRST_COMPLETED)

这给了我一个错误:

TypeError: 需要一个期货列表,而不是生成器

我了解此错误的来源,但不知道如何正确执行此操作。我怎样才能实现我上面描述的,即等到至少一个产生?

【问题讨论】:

    标签: python multithreading python-asyncio coroutine


    【解决方案1】:

    听起来你误解了生成器和协程的工作原理。

    协程是协作多任务的一种形式。它们不能同时运行。 Yielding 是协程暂停执行的方式,通常是因为它必须等待某些事情。

    Yielding 不是协程相互传递值的方式,yielding 并不意味着协程已经准备好任何结果。协程通常永远不会看到其他协程产生的值。事实上,在大多数 asyncio 代码中,协程将根本不会显式地让步 - 所有的让步都将作为awaiting 的一部分在可以让步的东西上执行。

    无论你想达到什么目标,你都在用错误的方式去做。最有可能的是,您实际上不应该使用 asyncio,或者实际上不应该使用 yield

    【讨论】:

    • @FalconUA:也许吧。这取决于这些函数的作用。
    【解决方案2】:

    首先,调用asyncio.wait 的正确方法是给它一个可等待对象序列作为第一个参数。例如(注意方括号):

    await asyncio.wait([coro1(), coro2()], return_when=...)
    

    其次,虽然 asyncio 在内部使用了生成器,但它不是一个用于使用 la itertools 生成器的库。它只是使用生成器作为实现可挂起协程(也称为基于生成器的协程)的一种方式。但是这些生成器必须以非常特定的方式运行 - 例如,它们产生的值不会被等待者观察到,它们会一直传播到事件循环。 awaiter观察基于生成器的协程返回的最终值,这对于普通的生成器没有意义,是专门为协程引入的。

    第三,asyncio.coroutine 装饰器和基于生成器的协程已被弃用,取而代之的是使用 async def 定义的本机协程,它们是在 Python 3.5 中引入的,应该在所有异步代码中使用。 async def 中的 yield 是允许的,但它实现了 asynchronous generator,即异步源上的生成器。

    使用实际的生成器时,您不需要 asyncio;相反,请查看itertools 和相关模块。对于这种特殊用途,要从多个生成器中提取第一个元素,您可能只需使用 next 函数:

    def extract_first(*iters):
        for it in iters:
            try:
                return next(it)
            except StopIteration:
                pass
        raise ValueError("all iterators are empty")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-15
      • 2018-11-21
      • 1970-01-01
      • 2020-09-12
      • 2019-04-11
      • 2015-12-07
      • 2018-09-16
      • 2022-01-13
      相关资源
      最近更新 更多