Future
A Future is an object that is supposed to have a result in the future.
Or more officially:
A Future is an awaitable object that represents an eventual result of an asynchronous operation.
Object is awaitable if it can be used in an await expression.
So, any Future can be await'ed.
Task
Docs:
Tasks are used to schedule coroutines concurrently.
When a coroutine is wrapped into a Task with functions like
asyncio.create_task() the coroutine is automatically scheduled to run
soon.
A Task actually is a Future:
A Future-like object that runs a Python coroutine.
Task is subclass of a Future.
asyncio.Taskinherits from Future all of its APIs except
Future.set_result() and Future.set_exception().
create_task(coro)
Docs:
Wraps the coro coroutine into a Task and schedules its execution.
Returns the Task object.
asyncio.ensure_future(obj, ...)
It actually ensures that obj is a Future. If it's not it creates a Task from obj. That's it.
Some conclusions
- If
obj already is a Future, ensure_future will return the same obj. In this case return value of a function may be a Future and not a Task - since Task is just a subclass of a Future.
- With
ensure_future you CAN do this:
# will create a Task
task = asyncio.ensure_future(coroutine())
# will ensure that it is a Task
task = asyncio.ensure_future(task)
or this:
# will create a Task
task = asyncio.create_task(coroutine())
# will ensure that it is a Task
task = asyncio.ensure_future(task)
So, you can call ensure_future on a Task.
But you CAN'T do the same with create_task:
# will create a Task
task = asyncio.create_task(coroutine())
# will raise an exception
task = asyncio.create_task(task)
TypeError: a coroutine was expected, got Task
Pay attention
According to docs:
create_task() is the preferred way for creating new Tasks.
Deprecated since version 3.10: Deprecation warning is emitted if obj
is not a Future-like object and loop is not specified and there is no
running event loop.