2016-12-30 14 views
0

Что было бы хорошим подходом к выполнению двух асинхронных циклов, работающих параллельно в Python, используя async/await?Две независимые асинхронные петли в Python

Я подумал о чем-то вроде кода ниже, но не могу обернуть вокруг себя, как использовать async/await/EventLoop в данном конкретном случае.

import asyncio 

my_list = [] 

def notify(): 
    length = len(my_list) 
    print("List has changed!", length) 

async def append_task(): 
    while True: 
     time.sleep(1) 
     await my_list.append(random.random()) 
     notify() 

async def pop_task(): 
    while True: 
     time.sleep(1.8) 
     await my_list.pop() 
     notify() 

loop = asyncio.get_event_loop() 
loop.create_task(append_task()) 
loop.create_task(pop_task()) 
loop.run_forever() 

Ожидаемый результат:

$ python prog.py 
List has changed! 1 # after 1sec 
List has changed! 0 # after 1.8sec 
List has changed! 1 # after 2sec 
List has changed! 2 # after 3sec 
List has changed! 1 # after 3.6sec 
List has changed! 2 # after 4sec 
List has changed! 3 # after 5sec 
List has changed! 2 # after 5.4sec 
+1

Так что выход вы получаете взамен? 'BaseEventLoop' не является конкретной реализацией цикла; используйте 'asyncio.get_event_loop()', чтобы получить конкретный цикл для вашей платформы. –

+0

Кроме того, операции 'list' не ожидаются. 'time.sleep()' не будет уступать другим сопрограммам. –

ответ

2

это работает отлично:

Примечание: вы хотите, чтобы ждать быстрых, не связанных И.О. операций (list.append и list.pop, которые даже не сопрограммы); что вы можете сделать, это awaitasyncio.sleep(...) (который является контролем сопрограммного и выхода обратно к абоненту):

import asyncio 
import random 

my_list = [] 


def notify(): 
    length = len(my_list) 
    print("List has changed!", length) 

async def append_task(): 
    while True: 
     await asyncio.sleep(1) 
     my_list.append(random.random()) 
     notify() 

async def pop_task(): 
    while True: 
     await asyncio.sleep(1.8) 
     my_list.pop() 
     notify() 


loop = asyncio.get_event_loop() 
cors = asyncio.wait([append_task(), pop_task()]) 
loop.run_until_complete(cors) 

time.sleep сами блокируют и не дружит с await.

+0

Не могли бы вы объяснить, что делать, если у меня есть функция блокировки (например, time.sleep())? Все примеры используют этот asyncio.sleep(), но у меня есть фактические длинные вычисления (или связанные с i/o вещи), и мне непонятно, как их обернуть, чтобы этот пример работал. Большое спасибо. – Fab

+0

@Fab: asyncio не поможет с функциями, связанными с процессором. и если ваш i/o-bound материал не построен на asyncio, он тоже не будет работать (поэтому 'time.sleep()' не работает, но 'asyncio.sleep()' does.) вам нужно вызвать сопрограммы которые возвращают программу обратно вызывающему абоненту, чтобы получить выгоду от цикла асинхронизации. –

+0

Большое спасибо, hiro. Это значительно облегчает ситуацию. Тогда я искал не то место! – Fab

1

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

Вы также хотите использовать asyncio.sleep(), а не time.sleep(); последние блоки.

Следующие работы просто прекрасны; Я добавил в метку времени в notify показать это прочь лучше:

from datetime import datetime 
# ... 

start = datetime.now() 
def notify(): 
    length = len(my_list) 
    print("t: {:.1f}, List has changed! {}".format(
     (datetime.now() - start).total_seconds(), length)) 

async def append_task(): 
    while True: 
     await asyncio.sleep(1) 
     my_list.append(random.random()) 
     notify() 

async def pop_task(): 
    while True: 
     await asyncio.sleep(1.8) 
     my_list.pop() 
     notify() 

Обратите внимание, что мы используем await на asyncio.sleep() вызова; который обеспечивает точку, в которой ваша сопрограмма ()) дает управление другой рутине.

Это дает:

$ python asyncio_demo.py 
t: 1.0, List has changed! 1 
t: 1.8, List has changed! 0 
t: 2.0, List has changed! 1 
t: 3.0, List has changed! 2 
t: 3.6, List has changed! 1 
t: 4.0, List has changed! 2 
t: 5.0, List has changed! 3 
t: 5.4, List has changed! 2 
t: 6.0, List has changed! 3 

 Смежные вопросы

  • Нет связанных вопросов^_^