Как использовать «yield» внутри асинхронной функции?

Я хочу использовать генератор yield и асинхронные функции. Я читаюЭта темаи написал следующий код:

import asyncio

async def createGenerator():
    mylist = range(3)
    for i in mylist:
        await asyncio.sleep(1)
        yield i*i

async def start():
    mygenerator = await createGenerator()
    for i in mygenerator:
        print(i)

loop = asyncio.get_event_loop()

try:
    loop.run_until_complete(start())

except KeyboardInterrupt:
    loop.stop()
    pass

Но я получил ошибку:

SyntaxError: «yield» внутри асинхронной функции

Как использовать генератор урожайности в асинхронной функции?

 vad07 июн. 2016 г., 08:50
 Ильдар31 мая 2016 г., 18:03
Может быть использовать событие? createGenerator будет устанавливать событие, а запуск будет ждать события. я написалэто решение, Это работает, но я хочу больше хорошего кода.
 reticentroot31 мая 2016 г., 17:45
Можете ли вы вернуть объект Future, а затем выдать этот объект, когда вам нужны его данные. Я никогда не использовал asyncio, но именно так это делается с Торнадо.
 Mikhail Gerasimov02 июн. 2016 г., 14:15
@ Ильдар ты видел второй ответ? Что ты думаешь об этом? Похоже, это работает.
 luk3231 мая 2016 г., 17:39
Это возможно? Похоже, два противоположных дизайна. Генераторы созданы так, чтобы не создавать ценность, если в этом нет необходимости, это означает, что им в принципе необходимогосударство. async с другой стороны, можно предположить, что вызываемая функция не может зависеть от своего состояния. В противном случае у вас будут данные гонки. Поддерживать асинхронные генераторы кажется действительно громоздким, их нужно будет обернуть блокирующими механизмами. Так что, вероятно, ответ на ваш вопрос находится где-то в этом направлении.
 syntonym31 мая 2016 г., 17:56
Я не думаю, что генератор asyncrounus имеет какой-либо смысл. Вы должны быть в состоянии вернуть генератор из асинхронной функции. Есть ли что-то, чего ты хочешь достичь или ты просто пытаешься что-то сделать?

Ответы на вопрос(3)

Новый Python 3.6 поставляется с поддержкой асинхронных генераторов.

ОПТОСОЗ 0525

Что нового в Python 3.6

PS: На момент написания Python 3.6 все еще бета. Если вы используете GNU / Linux или OS X и не можете ждать, попробуйте новый Python сpyenv.

Решение Вопроса

Upd:

Начиная с Python 3.6 мы имеемасинхронные генераторы и в состоянии использоватьyield прямо внутри сопрограмм.

import asyncio


async def async_generator():
    for i in range(3):
        await asyncio.sleep(1)
        yield i*i


async def main():
    async for i in async_generator():
        print(i)


loop = asyncio.get_event_loop()
try:
    loop.run_until_complete(main())
finally:
    loop.run_until_complete(loop.shutdown_asyncgens())  # see: https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.shutdown_asyncgens
    loop.close()

Старый ответ для Python 3.5:

Ты не можешьyield внутри сопрограмм. Единственный способ это реализоватьАсинхронный итератор вручную с помощью__aiter__/__anext__ магические методы. В твоем случае:

import asyncio


class async_generator:
    def __init__(self, stop):
        self.i = 0
        self.stop = stop

    async def __aiter__(self):
        return self

    async def __anext__(self):
        i = self.i
        self.i += 1
        if self.i <= self.stop:
            await asyncio.sleep(1)
            return i * i
        else:
            raise StopAsyncIteration


async def main():
    async for i in async_generator(3):
        print(i)


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

Выход:

0
1
4

Вот еще два примера:1, 2

 nawfal07 мар. 2018 г., 12:31
Все еще жду этого в C # :(
 NumesSanguis25 мая 2017 г., 10:14
На основе вашего кода Python 3.6 я сделал пример для использованияmatlibplot ибо если кому-то интересноstackoverflow.com/questions/44163601/...

Это должно работать с Python 3.6 (протестировано с 3.6.0b1):

import asyncio

async def createGenerator():
    mylist = range(3)
    for i in mylist:
        await asyncio.sleep(1)
        yield i*i

async def start():
    async for i in createGenerator():
        print(i)

loop = asyncio.get_event_loop()

try:
    loop.run_until_complete(start())

except KeyboardInterrupt:
    loop.stop()
    pass

Ваш ответ на вопрос