2016-06-25 70 views
10

PEP-492我想實現一個異步迭代器,這樣我可以做例如實現一個異步迭代器

async for foo in bar: 
    ... 

下面是一個簡單的例子,一個類似的文檔,用實例和異步迭代的一個非常基本的測試:

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 

然而,當我執行我的測試套件,我見:

=================================== 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看起來無效?至於我可以告訴它符合協議:

  1. 的對象必須實現一個__aiter__方法...返回異步迭代器對象。
  2. 異步迭代器對象必須實現一個__anext__方法...返回一個等待狀態。
  3. 停止迭代__anext__必須引發StopAsyncIteration異常。

這與Python的最新發布的版本(3.5.1),py.test(2.9.2)和pytest-asyncio(0.4.1)失敗。

+13

經過近3年,你終於[問了一個問題](http://stackoverflow.com/users/3001761/jonrsharpe?tab=questions)。榮譽 –

+6

@BhargavRao我感覺像2,076:1是正確的; o) – jonrsharpe

+0

適用於pytest 2.9.2。你使用什麼版本? –

回答

21

如果你讀它a little further down the documentation提到,(重點煤礦):

PEP 492在CPython的3.5.0接受了定義爲 方法__aiter__,這是有望重返的awaitable解析到 異步迭代器

在3.5.2中(因爲PEP 492被臨時接受), __aiter__協議被更新以直接返回異步迭代器。

因此,對於3.5.2之前的版本(2016/6/27發佈),該文檔與如何編寫工作異步迭代器的步驟略有不同。對於3.5.0和3.5.1固定的版本是這樣的:

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

這是在關閉bug #27243推出,是在data model documentation,這也暗示編寫向後兼容代碼的方式更清晰一點。

+10

3年後你不得不回答你自己的問題:) –

+2

@PadraicCunningham一些習慣很難打破... – jonrsharpe

+5

@Padraic [下一次jon問一個問題,遠離它](https:// www。 youtube.com/watch?v=4F4qzPbcFiA);) –