【问题标题】:Yielding from a factory generated by a pytest fixture从由 pytest 夹具生成的工厂产生
【发布时间】:2021-09-11 02:13:35
【问题描述】:

以下 pytest 夹具

@pytest.fixture(scope="module")
def gen_factory():
    def _gen_factory(owner: str):

        value = ...

        yield value

        print('gen teardown')

    yield _gen_factory

产生多次使用的工厂。

在一个测试用例中,我使用该夹具创建两个工厂并使用它们生成一些值:

@pytest.mark.asyncio
def test_case(gen_factory):
    gen1 = gen_factory('owner1')
    gen2 = gen_factory('owner2')
    val1 = next(gen1)
    val2 = next(gen2)

    ...

    next(gen1)
    next(gen2)

发生的情况是 print('gen teardown') 仅被调用一次,然后循环关闭,第二个 next() 调用引发 StopIteration 错误。

我在这里缺少什么?为什么第二次打印没有发生?

【问题讨论】:

    标签: python pytest generator factory fixtures


    【解决方案1】:

    错误发生在第二次调用next(gen1) 的(最后一个)行上,在它执行最后一个语句(next(gen2))之前。迭代器已用尽。这就是生成器的工作原理。 StopIteration 在生成器末尾引发,(这就是打印第一个的原因!)一旦它们没有要迭代的项目,除非将默认值传递给内置 @987654325 @ 功能。 StopIteration 使 for 循环停止。尽管生成器可以以不同的方式使用,但它们的使用主要是在 for 循环中进行迭代。这就是为什么默认情况下会引发此“异常”。

    如果您不想更改夹具中的任何内容,只需将最后一次调用更改为next

    next(gen1, None)
    

    使用默认值不会引发StopIteration

    另一种方法是让_gen_factory 成为上下文管理器:

    from contextlib import contextmanager
    
    def gen_factory():
        @contextmanager
        def _gen_factory(owner):
            value = owner
            yield value
            print('gen teardown')
        yield _gen_factory
        
    
    def test_case(genfactory):   
        with genfactory('owner1') as own1, genfactory('owner2') as own2:
            print(own1, own2)
    

    看到这个tutorial on generators

    【讨论】:

    • 为什么第二次打印没有发生?在第一个生成器拆除后,事件循环关闭,第二个将保持挂起
    • 因为错误发生在它在next(gen1)上打印第二次拆解之前
    • 我更新了我的答案。对你现在理解有帮助吗?
    • 也许我仍然没有得到它,但为什么在调用 next(gen1)next(gen2) 之后什么都没有打印出来?我原以为两个生成器都会用尽,但调试我发现yield value 之后的代码没有执行
    • 正如我所解释的,StopIteration 被提出。尝试仅将 next(gen1) 更改为 next(gen1, None)。您将看到错误将出现在具有next(gen2) 的行中。正如我所解释的,最后一次调用必须提供一个默认值。你只有一个 yield 语句,相当于一个next。没有要迭代的项目了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-14
    • 1970-01-01
    相关资源
    最近更新 更多