Создание асинхронных циклов в Python - PullRequest
0 голосов
/ 26 ноября 2018

Следующий код выводит следующее:

1 sec delay, print "1", 
1 sec delay, print "2", 
1 sec delay, print "1", 
1 sec delay, print "2"

Как его можно изменить для запуска следующим образом:

1 sec delay, print "1", print "1",
1 sec delay, print "2", print "2"

Я бы хотел, чтобы он выполнялся так, чтобы оба экземплярацикл for начинает выполняться одновременно.При выполнении каждого экземпляра они одновременно сталкиваются с функцией first (), а затем с функцией second (), печатая в указанном выше порядке.

Код:

import asyncio

async def first():
    await asyncio.sleep(1)
    return "1"

async def second():
    await asyncio.sleep(1)
    return "2"

async def main():     
    for i in range(2):
      result = await first()
      print(result)
      result2 = await second()
      print(result2)


loop = asyncio.get_event_loop()
loop.run_until_complete(main())

Ответы [ 3 ]

0 голосов
/ 26 ноября 2018

Для одновременного запуска двух функций вы можете использовать gather.Однако результаты будут предоставлены вам в том порядке, в котором вы их предоставили.Например, если вы сделаете

results = await asyncio.gather(first(), second())

, вы получите [the result of first(), the result of second()] обратно.Если вы хотите что-то делать всякий раз, когда каждый возвращается, вам следует явно использовать Tasks и добавить обратные вызовы .

0 голосов
/ 26 ноября 2018

Глядя на желаемый результат, кажется, что цель состоит в том, чтобы оставить отдельную итерацию такой, какой она есть - т.е. запустить first и second последовательно - но выполнить обе итерации цикла параллельно.

Предполагая, чтоВы хотите изменить только main(), это может быть достигнуто следующим образом:

async def main():
    async def one_iteration():
        result = await first()
        print(result)
        result2 = await second()
        print(result2)
    coros = [one_iteration() for _ in range(2)]
    await asyncio.gather(*coros)

Вместо последовательной итерации вышеописанное создает сопрограмму для каждой итерационной задачи и использует asyncio.gather для выполнения всех итераций параллельно.

Обратите внимание, что простое создание сопрограммы не начинает ее выполнять, поэтому большое количество coros не будет блокировать цикл обработки событий.

0 голосов
/ 26 ноября 2018

С библиотекой aysncio вы можете использовать aysncio.gather ()

loop.run_until_complete(asyncio.gather(
  first(),
  second()
))

Это может пригодиться, если вы также отправляете HTTP-запросы параллельно:

loop.run_until_complete(asyncio.gather(
  request1(),
  request2()
))
...