Python асинхронный / ожидает разницы во времени выполнения

#python #python-3.x #async-await #python-asyncio

#python #python-3.x #async-ожидание #python-asyncio

Вопрос:

Я рассчитываю время выполнения двух методов, используя асинхронный ввод-вывод

СЛУЧАЙ 1:

 async def test():    
    print(f"started at {time.strftime('%X')}")
    await asyncio.create_task(say_after(2, 'hello'))
    await asyncio.create_task(say_after(4, 'world'))    
    print(f"finished at {time.strftime('%X')}")
  

и это ответ :

 started at 12:31:05
hello
world
finished at 12:31:11
  

всего 6 секунд

СЛУЧАЙ 2:

 async def test():    
    print(f"started at {time.strftime('%X')}")
    t1=asyncio.create_task(say_after(2, 'hello'))
    t2= asyncio.create_task(say_after(4, 'world'))    
    await t1
    await t2
    print(f"finished at {time.strftime('%X')}")
  

и это ответ :

 started at 12:31:05
hello
world
finished at 12:31:09
  

всего 4 секунды

почему это так?

Комментарии:

1. Поскольку задача начинает выполняться при ее создании, что означает, что ваши задачи будут выполняться «параллельно», если вы сначала создадите обе, а затем будете ожидать их (поскольку первая задача напрямую достигнет своего условия приостановки ( say_after ), а затем разрешит запуск следующей задачи.

Ответ №1:

В первом примере вы создаете по запросу, ждете его завершения, затем создаете другую задачу и ждете завершения этой другой задачи. Вы выполняете задачи последовательно.

Во втором примере вы создаете две задачи, затем, после того как они обе созданы, ожидаете завершения двух. Вы выполняете задачи одновременно.

Выполнение задач друг за другом занимает 2 4 = 6 секунд, но при последовательном выполнении вам нужно подождать всего 4 секунды для завершения второй, более длинной задачи, в то время как более короткая задача за 2 секунды завершена за некоторое время до этого:

 # sequentially

| start task 1
V
 ------------- 
| 2 seconds   |
 ------------- 
              ^
await returns |

                | start task 2
                V
                 -------------------------- 
                | 4 seconds                |
                 -------------------------- 
                                           ^
                             await returns |

# consecutively

| start task 1
V
 ------------- 
| 2 seconds   |
 ------------- 
              ^
await returns |

| start task 2
V
 -------------------------- 
| 4 seconds                |
 -------------------------- 
                           ^
             await returns |
  

Разница заключается в вызове, asyncio.create_task() а не в немедленном ожидании выполнения задач, потому что await task не завершится, пока задача не будет завершена.

В разделеЗадачи«Ожидаемые» приведен пример:

 async def main():
    # Schedule nested() to run soon concurrently
    # with "main()".
    task = asyncio.create_task(nested())

    # "task" can now be used to cancel "nested()", or
    # can simply be awaited to wait until it is complete:
    await task
  

Обратите внимание на расписание nested() для запуска в ближайшее время одновременно с «main()» и или может просто быть отложено, чтобы дождаться завершения комментариев.

Задачи являются специализированными Future подклассами, поэтому документация для asyncio.Future здесь тоже уместна:

Future — это ожидаемый объект. Сопрограммы могут ожидать будущих объектов до тех пор, пока у них не будет результата или установленного исключения, или пока они не будут отменены.

Комментарии:

1. в документации следует добавить это, в основном, await t1 в случае, если 2 не требуется, поскольку await t2 будет ждать 4 секунды. Спасибо

2. @JibinMathews: это зависит от приложения, а не от того, что документация может сказать вам, когда ожидать, а когда нет.