简体   繁体   中英

Python asyncio: Future vs Task

This creates a future

loop.run_in_executor(None, some_fn)

This creates a task

asyncio.create_task(some_fn())

What is the difference between the two?

According to my understanding:

The former spins up another thread and executes the function (which is typically IO-bound) concurrently.

The latter creates a task within the same thread and executes the function concurrently.

Is this correct? The documentation isn't really helpful in understanding the differences between the two.

What is the difference between [futures and tasks]?

In short, future is the more general concept of a container of an async result, akin to a JavaScript promise. Task is a subclass of future specialized for executing coroutines.

Nothing in the definition of asyncio future indicates multi-threaded execution, and asyncio is in fact strongly single-threaded. It's a specific feature of run_in_executor that it safely synchronizes functions it invokes in other threads with an asyncio future it creates and returns.

Also, be careful not to confuse asyncio futures with concurrent.futures futures , the latter being indeed multi-threaded. Despite similarities in the API coming from the fact that asyncio futures were inspired by the ones from concurrent.futures , they work in conceptually different ways and cannot be used interchangeably.

*My answers are assuming you use the default loops provided by Python based on your OS with CPython.

The asyncio.create_task method is used to schedule the execution of a coroutine (here some_fn ) on the event loop. Since the event loop runs on a single thread, the coroutine will be executed asynchronously to the current context by using cooperative multitasking.

Contrary to that, loop.run_in_executor(None, some_fn) , will use the ThreadPoolExecutor to create a thread pool, and perform the tasks, usually BlockingIO, with preemptive multitasking. You can see here the implementation for ThreadPoolExecutor in CPython. In the implementation, you'll see that it creates a queue and a pool of threads which will get tasks from the queue and perform them. So yes - it will create a new thread for your scheduled task.


A couple of notes:

  1. A Task is a Future
  2. Generally speaking, if your code does not have blockingIO methods, and you can leverage asyncio for all your IOs, you will be better just using the event loop, without the need to use an Executor explicitly. This will be both more efficient since your code now uses cooperative multitasking, and will simplify execution since you know when your code gives back control to the event loop, thus managing concurrency (eg race condition) is either very simple or even non-existent.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM