Актуальна інформація:
Починаючи з 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
лише в тому випадку, якщо ви збираєтесь реалізувати власний тип циклу подій.
Оновлено:
@ bj0 вказав на відповідь Гідо на цю тему:
Сенс у ensure_future()
тому, що якщо у вас є щось, що може бути або підпрограмою, або a Future
(останній включає в себе а, Task
тому що це підклас Future
), і ви хочете мати можливість викликати на ньому метод, який визначений лише Future
(можливо, про єдиний корисний приклад буття cancel()
). Коли це вже Future
(або Task
), це нічого не робить; коли це супровід, він загортає його в Task
.
Якщо ви знаєте, що у вас є програма, і ви хочете, щоб це було заплановано, правильним API є create_task()
. Єдиний час, коли вам слід дзвонити, ensure_future()
- це коли ви надаєте API (як і більшість власних API API), який приймає або програму, або а, Future
і вам потрібно зробити щось для цього, що вимагає, щоб ви мали Future
.
і пізніше:
Зрештою, я все-таки вважаю, що ensure_future()
це належним чином незрозуміле ім'я для рідко потрібної функції. Створюючи завдання зі спільної програми, ви повинні використовувати відповідну назву
loop.create_task()
. Може, для цього повинен бути псевдонім
asyncio.create_task()
?
Для мене це дивно. Моя основна мотивація використовувати ensure_future
весь час - це функція вищого рівня порівняно з членом циклу create_task
(обговорення містить деякі ідеї, такі як додавання asyncio.spawn
чи asyncio.create_task
).
Я також можу зазначити, що на мою думку, досить зручно використовувати універсальну функцію, яка може справлятись лише з будь-якими, Awaitable
а не з супроводуми.
Однак відповідь Гвідо зрозуміла: "Створюючи завдання за допомогою програми, ви повинні використовувати відповідне ім'я loop.create_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')
# Now you want to start long_operation, but you don't want to wait it finised:
# long_operation should be started, but second msg should be printed immediately.
# Create task to do so:
task = asyncio.ensure_future(long_operation())
await msg('second')
# Now, when you want, you can await task finised:
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/isissue/477#issuecomment-268709555