Актуальная информация:
Начиная с Python 3.7 для этого была добавленаasyncio.create_task(coro) высокоуровневая функция .
Вы должны использовать его вместо других способов создания задач из сопрограмм. Однако, если вам нужно создать задачу из произвольного объекта ожидания, вы должны использовать asyncio.ensure_future(obj).
Старая информация:
ensure_future против create_task
ensure_futureэто метод создания Taskиз coroutine. Он создает задачи по-разному на основе аргументов (в том числе с использованием create_taskсопрограмм и будущих объектов).
create_taskэто абстрактный метод AbstractEventLoop. Различные циклы событий могут реализовать эту функцию по-разному.
Вы должны использовать ensure_futureдля создания задач. Вам понадобится create_taskтолько в том случае, если вы собираетесь реализовать собственный тип цикла событий.
Upd:
@ bj0 указал на ответ Гвидо по этой теме:
Дело в ensure_future()том, что если у вас есть что-то, что может быть либо сопрограммой, либо Future(последний включает в себя, Taskпотому что это подкласс Future), и вы хотите иметь возможность вызывать на нем метод, который определен только Future(вероятно, о единственном полезный пример существа cancel()). Когда это уже Future(или Task), это ничего не делает; когда это сопрограмма, она оборачивается в Task.
Если вы знаете, что у вас есть сопрограмма, и вы хотите, чтобы она была запланирована, правильный API для использования - create_task(). Единственный раз, когда вы должны звонить, ensure_future()- это когда вы предоставляете API (например, большинство собственных API asyncio), который принимает либо сопрограмму, либо a, Futureи вам нужно что-то сделать с ним, что требует наличия Future.
и позже:
В конце концов, я все еще считаю, что ensure_future()это достаточно неясное название для редко необходимой части функциональности. При создании задачи из сопрограммы вы должны использовать файл с соответствующим именем
loop.create_task(). Может быть, для этого должен быть псевдоним
asyncio.create_task()?
Для меня это удивительно. Моей основной мотивацией для использования ensure_futureвсегда было то, что это функция более высокого уровня по сравнению с членом цикла create_task(обсуждение содержит некоторые идеи, такие как добавление asyncio.spawnили asyncio.create_task).
Также могу отметить, что, на мой взгляд, довольно удобно использовать универсальную функцию, которая может обрабатывать любые, Awaitableа не только сопрограммы.
Однако ответ Гвидо ясен: «При создании задачи из сопрограммы вы должны использовать соответствующий названный loop.create_task()»
Когда сопрограммы следует заключать в задачи?
Обернуть сопрограмму в Task - это способ запустить эту сопрограмму «в фоновом режиме». Вот пример:
import asyncio
async def msg(text):
await asyncio.sleep(0.1)
print(text)
async def long_operation():
print('long_operation started')
await asyncio.sleep(3)
print('long_operation finished')
async def main():
await msg('first')
task = asyncio.ensure_future(long_operation())
await msg('second')
await task
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Выход:
first
long_operation started
second
long_operation finished
Вы можете заменить asyncio.ensure_future(long_operation())на, await long_operation()чтобы почувствовать разницу.
create_taskесли вам действительно нужен объект задачи, который обычно вам не нужен: github.com/python/asyncio/issues/477#issuecomment-268709555