Визуализация выполнения асинхронных сопрограмм - PullRequest
2 голосов
/ 24 апреля 2019

Я пытаюсь понять, как выполняются асинхронные сопрограммы. Допустим, у меня есть эта функция

async def statemachine(state):

, что делает следующее:

  1. Считать значение на удаленном сервере
  2. Запись на удаленный сервер MySQL
  3. Запись на локальный сервер redis
  4. Удалить запись с удаленного сервера MySQL
  5. Создание события и уведомление о выполнении сопрограммы завершено

Поскольку async приостанавливает выполнение, чтобы дать другим сопрограммам время для выполнения, выполнение всегда будет начинаться с шага 1 до шага 5.

1 Ответ

2 голосов
/ 24 апреля 2019

Сопрограмма всегда выполняется последовательно. Однако многие (со) подпрограммы могут (со) работать вместе, находясь под контролем цикла событий или своего рода планировщика.

Так что, если вы сложите все свои задачи в одну сопрограмму, например:

async def statemachine(state):
    await read_value_on_remote_server()
    await write_to_remote_mysql_server()
    await write_to_local_redis_server()
    await delete_a_record_from_a_remote_mysql_server()
    await create_event_and_notify_coroutine_execution_has_finished()

ваш statemachine будет ждать каждую задачу один за другим, пока они не будут выполнены. Этот сценарий не очень полезен и не дает никакой выгоды по сравнению с кодом синхронизации.

Сценарий, в котором выполняется асинхронное выполнение, скажем, у вас есть веб-приложение, которое планирует одну statemachine сопрограмму на запрос пользователя. Теперь каждый раз, когда пользователь обращается к вашему серверу с запросом, в eventloop запланируется новая сопрограмма. И поскольку цикл обработки событий может запускать только одну вещь за один раз (псевдо-параллелизм), он будет выполнять каждую сопрограмму (допустим, используя алгоритм циклического перебора) до тех пор, пока он не приостановится, потому что они ожидают объект или другую сопрограмму, которая является в ожидании другого объекта.

Способ, которым сопрограмма приостанавливается, заключается в том, чтобы получить заявление в ожидании. Это позволяет циклу событий знать, что сопрограмма ожидает операцию, которая не обязательно связана с процессором. например сетевой вызов или ввод пользователя.

К счастью, мы защищены от подробностей реализации eventloop и того, как ему удается узнать, когда сопрограмму следует возобновить. Обычно это делается с использованием библиотеки, такой как Python stdlib select https://docs.python.org/2/library/select.html.

В большинстве случаев вы должны знать, что сопрограмма всегда выполняется последовательно и что цикл обработки событий - это то, что управляет выполнением сопрограмм с помощью кооперативных методов (в отличие, например, от стандартного планировщика ОС).

Если вы хотите запустить несколько сопрограмм псевдо-одновременно, вы можете посмотреть asycio.gather или более правильный asyncio.create_task. Надеюсь, это поможет.

...