Когда задача в create_task () `выполняется в asyncio? - PullRequest
0 голосов
/ 03 мая 2018

В следующем коде:

import asyncio

async def task_func():
    print('in task_func')
    return 'the result'


async def main(loop):
    print('creating task')
    task = loop.create_task(task_func())
    print('waiting for {!r}'.format(task))
    await asyncio.sleep(2)
    return_value = await task
    print('task completed {!r}'.format(task))
    print('return value: {!r}'.format(return_value))


event_loop = asyncio.new_event_loop()
try:
    event_loop.run_until_complete(main(event_loop))
finally:
    event_loop.close()

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

creating task
waiting for `<Task pending coro=<task_func() running at <ipython-input-29-797f29858344>:1>>`
in task_func
task completed `<Task finished coro=<task_func() done, defined at <ipython-input-29-797f29858344>:1> result='the result'>`
return value: 'the result'

Но я не понимаю, когда выполняется код, установленный на loop.create_task(task_func()). В частности, я предполагал, что когда вы добавляете задачу в цикл событий, она скоро выполняется, поэтому я подумал, что in task_func будет напечатано до waiting for <Task....

Затем я обнаружил, что всегда выполняется после waiting for <Task..., поэтому я добавил await asyncio.sleep(2), но обнаружил, что in task_func печатается до окончания 2 секунд.

Я также добавил task_func_2(), который практически совпадает с task_func(), и создайте его задачу ниже task = loop.create_task(task_func()), но НЕ добавляйте return_value_2 = await task2, поэтому await не выполняет задачу (в противном случае task_func_2() никогда не выполняется).

Так что теперь я получил признание. Когда задача выполняется после ее добавления в цикл обработки событий в loop.create_task()?

1 Ответ

0 голосов
/ 03 мая 2018

В частности, я предполагал, что когда вы добавляете задачу в цикл обработки событий, она скоро выполняется, поэтому я подумал, что in task_func будет напечатано до waiting for <Task....

«Выполнено в ближайшее время» не означает «выполнено сразу». Вместо этого вы можете думать об этом как о «выполнившем первый шанс, который мы получим», we - цикл обработки событий. Поскольку print сразу же следует за вызовом create_task, в этот момент цикл событий еще не имел возможности вообще работать. Чтобы дать возможность запустить цикл обработки событий, вы должны вернуться в цикл обработки событий, либо вернувшись из текущей сопрограммы, либо ожидая чего-то, что блокирует.

Когда вы await блокируете сопрограмму, такую ​​как asyncio.sleep(), сопрограмма временно приостанавливает себя и передает управление циклу событий. Цикл событий посмотрит, что еще нужно сделать до того, как пройдет сон, и найдет задачи, запланированные с помощью create_task, в своей очереди выполнения. Вот почему task_func и task_func_2 выполняются, когда сопрограмма main ожидает сна - но не раньше этого, и независимо от того, вы await особенно их или что-то еще, что блокирует.

await Подпрограмма, такая как task_func, означает запросить его результат тут же и быть готовым ждать его. (Такое ожидание автоматически откладывает выполнение до цикла обработки событий, позволяя другим сопрограммам добиться прогресса.) Хотя реализация отличается, await концептуально аналогичен join созданию потока.

...