实现异步迭代器 [英] Implementing an asynchronous iterator

查看:90
本文介绍了实现异步迭代器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

每个 PEP-492 我正在尝试实现一个异步迭代器,这样我就可以做到

Per PEP-492 I am trying to implement an asynchronous iterator, such that I can do e.g.

async for foo in bar:
    ...

这是一个简单的示例,类似于文档中的示例,它对实例化和异步迭代进行了非常基本的测试:

Here is a trivial example, similar to the one in the docs, with a very basic test of instantiation and async iteration:

import pytest

class TestImplementation:
    def __aiter__(self):
        return self
    async def __anext__(self):
        raise StopAsyncIteration


@pytest.mark.asyncio  # note use of pytest-asyncio marker
async def test_async_for():
    async for _ in TestImplementation():
        pass

但是,当我执行测试套件时,我看到:

However, when I execute my test suite, I see:

=================================== FAILURES ===================================
________________________________ test_async_for ________________________________

    @pytest.mark.asyncio
    async def test_async_for():
>       async for _ in TestImplementation():
E       TypeError: 'async for' received an invalid object from __aiter__: TestImplementation

...: TypeError
===================== 1 failed, ... passed in 2.89 seconds ======================

为什么我的 TestImplementation 无效?据我所知,它符合协议:

Why does my TestImplementation appear to be invalid? As far as I can tell it meets the protocol:

  1. 对象必须实现 __ aiter __ 方法...返回异步迭代器对象.
  2. 一个异步迭代器对象必须实现一个 __ anext __ 方法...返回一个等待的对象.
  3. 要停止迭代, __ anext __ 必须引发 StopAsyncIteration 异常.
  1. An object must implement an __aiter__ method ... returning an asynchronous iterator object.
  2. An asynchronous iterator object must implement an __anext__ method ... returning an awaitable.
  3. To stop iteration __anext__ must raise a StopAsyncIteration exception.

使用最新版本的Python(3.5.1), py.test (2.9.2)和 pytest-asyncio (0.4.1)失败

This is failing with the latest released versions of Python (3.5.1), py.test (2.9.2) and pytest-asyncio (0.4.1).

推荐答案

如果您阅读

PEP 492在CPython 3.5.0中被接受,其中 __ aiter __ 定义为方法,该方法应将可以解决的问题返回给异步迭代器.

PEP 492 was accepted in CPython 3.5.0 with __aiter__ defined as a method, that was expected to return an awaitable resolving to an asynchronous iterator.

在3.5.2中(由于PEP 492被临时接受) __ aiter __ 协议已更新,可以直接返回异步迭代器.

In 3.5.2 (as PEP 492 was accepted on a provisional basis) the __aiter__ protocol was updated to return asynchronous iterators directly.

因此,对于3.5.2之前的版本(2016年6月27日发行),该文档与如何编写有效的异步迭代器有些矛盾.3.5.0和3.5.1的固定版本如下:

Therefore for versions prior to 3.5.2 (released 2016/6/27) the documentation is slightly out of step with how to write a working asynchronous iterator. The fixed version for 3.5.0 and 3.5.1 looks like:

class TestImplementation:
    async def __aiter__(self):
  # ^ note
        return self
    async def __anext__(self):
        raise StopAsyncIteration

这是在关闭 bug#27243 时引入的,在

This was introduced on closing bug #27243 and is a little clearer in the data model documentation, which also suggests a way of writing backwards compatible code.

这篇关于实现异步迭代器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆