2016-06-25 13 views
10

Per PEP-492 Sto tentando di implementare un iteratore asincrono, tale che posso fare ad es.Implementazione di un iteratore asincrono

async for foo in bar: 
    ... 

Ecco un esempio banale, simile a quello nella documentazione, con un test di base di esemplificazione e l'iterazione async:

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 

Tuttavia, quando eseguo la mia suite di test, vedo :

=================================== 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 ====================== 

Perché il mio TestImplementation sembra essere valida? Per quanto posso dire che incontra il protocollo:

  1. Un oggetto deve implementare un metodo __aiter__ ... restituisce un oggetto iteratore asincrono.
  2. Un oggetto iteratore asincrono deve implementare un metodo __anext__ ... restituendo un aspetto attendibile.
  3. Per interrompere l'iterazione __anext__ è necessario generare un'eccezione StopAsyncIteration.

Questo sta fallendo con le ultime versioni rilasciate di Python (3.5.1), py.test (2.9.2) e pytest-asyncio (0.4.1).

+13

Dopo quasi 3 anni, hai finalmente [fatto una domanda] (http://stackoverflow.com/users/3001761/jonrsharpe?tab=questions). Complimenti –

+6

@BhargavRao Mi sono sentito come 2.076: 1 riguardava la parte destra; o) – jonrsharpe

+0

Funziona per me con pytest 2.9.2. Che versione stai usando? –

risposta

21

Se leggete a little further down the documentation si menziona che (sottolineatura mia):

PEP 492 è stata accettata in CPython 3.5.0 con __aiter__ definita come metodo di , che ci si aspettava per tornare un awaitable risolvere a un iteratore asincrono.

In 3.5.2 (poiché PEP 492 è stato accettato in via provvisoria) il protocollo __aiter__ è stato aggiornato per restituire direttamente iteratori asincroni.

Pertanto per le versioni precedenti alla 3.5.2 (versione 2016/6/27) la documentazione è leggermente sfasata rispetto alla modalità di scrittura di un iteratore asincrono funzionante. La versione fissa per la 3.5.0 e 3.5.1 si presenta come:

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

Questo è stato introdotto in chiusura bug #27243 ed è un po 'più chiaro nella data model documentation, che suggerisce anche un modo di scrivere codice compatibile.

+10

Dopo 3 anni dovevi rispondere alla tua stessa domanda :) –

+2

@PadraicCunningham alcune abitudini sono difficili da rompere ... – jonrsharpe

+5

@Padraic [La prossima volta che jon fa una domanda, starne alla larga] (https: // www. youtube.com/watch?v=4F4qzPbcFiA);) –

Problemi correlati