Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

268
Visualizações
Async generator is not an iterator?

In Python you can write a generator that is iterable like:

def generate(count):
    for x in range(count):
        yield x

# as an iterator you can apply the function next() to get the values.
it = generate(10)
r0 = next(it)
r1 = next(it) ...

When trying to use an async iterator, you get the 'yield inside async' error. The suggested solution is to implement your own generator:

class async_generator:
    def __aiter__(self):
        return self

    async def __anext__(self):
        await asyncio.sleep()
        return random.randint(0, 10)
        
# But when you try to get the next element
it = async_generator(10)
r0 = next(it)

You get the error "async_generator" object is not an iterator

I think that if you are going to call something an Iterator it's because it has exactly the same interface, so I can just write async iterators and use on a framework that relies heavily on next() calls. Any new Python capability is pointless if you need to rewrite your entire code to be able to use async.

Am I missing something?

Thanks!

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

So, as @bosnjak said, you can use async for:

async for ITEM in A_ITER:
    BLOCK1
else: # optional
    BLOCK2

But if you want to iterate manually, you can simply write:

it = async_iterator()
await it.__anext__()

But I wouldn't recommend to do that.

I think that if you are going to call something an Iterator its because it has exactly the same interface, so I can just write async iterators and use on a framework that relies heavily on next() calls

No, acutally it's not the same. There is a difference between regular synchronous iterators and asynchronous ones. And there few reasons for that:

  1. Python coroutines are built on top of generators internally
  2. According to Zen of python, explicit is better than implicit. So that you will actually see, where code can be suspended.

That's why it's impossible to use iter and next with asynchronous iterators. And you cannot use them with frameworks that expects synchronous iterators. So if you are going to make your code asynchronous, you have to use asynchronous frameworks as well. Here are few of them.

Also, I would like to say a few words about iterators and generators. Iterator is a special object that has __iter__ and __next__ methods. Whereas generator is a special function containing yield expression. Every generator is an iterator, but not vice versa. The same thing is acceptable to asynchronous iterators and generators. Yes, since python 3.6 you are able to write asynchronous generators!

async def ticker(delay, to):
    for i in range(to):
        yield i
        await asyncio.sleep(delay)

You can read PEP 525 for more details

over 4 years ago · Santiago Trujillo Relatório

0

I believe a new statement was introduced for async generators:

async for TARGET in ITER:
    BLOCK
else:
    BLOCK2

according to PEP 492.

Basically, this would mean you should do:

async for number in generate(10):
        print(number)

Also, check the Differences from generators:

Native coroutine objects do not implement iter and next methods. Therefore, they cannot be iterated over or passed to iter() , list() , tuple() and other built-ins. They also cannot be used in a for..in loop. An attempt to use iter or next on a native coroutine object will result in a TypeError .

over 4 years ago · Santiago Trujillo Relatório

0

I used this to async loop through a list

class AsyncRange(object):
    def __init__(self, length):
        self.length = length
        self.i = 0

    async def __aiter__(self):
        return self

    async def __anext__(self):
        index = self.i
        self.i += 1
        if self.i <= self.length:
            return index
        else:
            raise StopAsyncIteration

then simply:

async for i in AsyncRange(my_list):
    # your code
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda