Python Module - concurrent.futures

Learn via video course
FREE
View all courses
Python Course for Beginners With Certification: Mastering the Essentials
Python Course for Beginners With Certification: Mastering the Essentials
by Rahul Janghu
1000
4.90
Start Learning
Python Course for Beginners With Certification: Mastering the Essentials
Python Course for Beginners With Certification: Mastering the Essentials
by Rahul Janghu
1000
4.90
Start Learning
Topics Covered

Overview

The python concurrent futures offers a high-level interface for callables that are executed asynchronously. Using ThreadPoolExecutor or ProcessPoolExecutor, the asynchronous execution can be carried out concurrently or in separate processes. The abstract Executor class defines an interface that is implemented by both.

About Python Module - concurrent.futures

Python's concurrent.futures module provides a high-level interface for executing asynchronous processes using a pool of threads or processes. It simplifies multi-threaded and multi-process programming, allowing developers to focus on their core competencies. With this module, developers can easily create and execute futures, resulting in significant speedups for CPU-bound tasks. Overall, concurrent.futures is a valuable addition to Python's standard library.

Executor Class

Asynchronous call execution is possible with the help of the abstract class known as Executor. With the help of the ThreadPoolExecutor or the ProcessPoolExecutor, separate processes or threads can carry out the asynchronous execution. The abstract Executor class defines an interface that both classes implement.

Creating a Process Pool Executor

The Python concurrent.futures module contains the ProcessPoolExecutor Python class, which is used to set up and manage process pools.

To create a process pool executor, it is essential to create a ProcessPoolExecutor instance first. The set number of processes in the pool, the procedure for adding new processes, the name of a function to run when initializing each process, and any parameters for the function must all be specified when an instance of a ProcessPoolExecutor is created.

Instantiation of ProcessPoolExecutor Class

ProcessPoolExecuter class can be instantiated using a context manager. This aligns with how files and sockets are often used to interact with other resources. The "with" keyword is used to construct a block in which the ProcessPoolExecutor may be used to run tasks and provide results when used with a context manager. The process pool is shut down automatically when the block has finished. When all tasks that are currently queued and in execution have finished, the context manager will internally call the shutdown() method with the default arguments before returning and continuing.

Uses of Function Executor.map()

Many different tasks can be accomplished with the map() function in Python. One such task is to give each element in iterables a specific function. Similar to this, we can map every iterator component to a function and send these as separate tasks to the ProcessPoolExecutor. In essence, it is a more efficient approach than to create a for loop and store the futures.

Processpool Executor vs Threadpool Executor

1. Threads and processes- The category of workers each class employs may be the most clear disparity. The ThreadPoolExecutor and the ProcessPoolExecutor, as their names imply, internally utilise threads and processes, respectively. A process can have extra threads in addition to its main thread. The base operating system provides both processes and threads as functionalities. The abstraction level of a process is higher than that of a thread. This difference defines all additional distinctions between the two groups.

2. GIL vs. no GIL

The global interpreter lock (GIL) applies to multiple threads running in a ThreadPoolExecutor but not to numerous child processes running in a ProcessPoolExecutor. In the default Python interpreter, the GIL is a programming pattern. In the sense that it employs synchronization to guarantee that only a single thread of execution may carry out instructions at once within a Python process, it functions as a valve. This indicates that despite the possibility of having several threads in a ThreadPoolExecutor, only a single thread can run at once. Inside every Python process, the GIL is used, but not between processes. This indicates that numerous child processes running under a ProcessPoolExecutor can do so concurrently and are not bound by the GIL.

3. Shared Memory vs. Inter-Process Communication

The methods through which the classes access shared state varies significantly from one another. Within a process, threads are able to share memory. This implies that the ThreadPoolExecutor's worker threads have access to the same information and state. These might be shared data through function arguments or global variables. Sharing state between threads is therefore simple. Unlike threads, processes are not equipped with shared memory. Instead, inter-process communication, also known as serialization, is required to transfer state across processes. Although it goes unnoticed, it does place restrictions on the types of data and states that may be communicated and raises the cost of doing so. As a result, exchanging state across processes is more difficult and bulky than sharing state between threads.

Examples for Understanding

Example 1:

The code below illustrates how to implement ThreadPoolExecutor. This straightforward basic example shows you how to create your own ProcessPoolExecutor and submit and map tasks to this pool. The constructor takes care of everything when the threads are completed, making the code short and error-free.

Output

Example 2:

A ProcessPoolExecutor has been built with three threads in the example below. Then a work() is sent to the process pool executor that will wait for two seconds before sending the text message. The result indicates that the job does not finish until 2 seconds have passed, hence the call to done() will return False. The job is completed after two seconds, at which point we use the result() function on the future to obtain the outcome.

Output

Example 3:

The code below makes an HTTP request to retrieve items from the internet; we are using the request library to do this. The first piece of the code calls the API one at a time, which causes the fetch to be slow, but the second section uses threads to perform a simultaneous request for the API.

Output

Conclusion

  • Python Concurrent futures is a module included in the Python standard library. This module was included in Python 3.2 to provide programmers with a high-level interface for running asynchronous processes.
  • As implied by their names, the ThreadPoolExecutor and the ProcessPoolExecutor, respectively use threads and processes internally.
  • The ProcessPoolExecutor Python class, used to create and manage process pools, is part of the concurrent.futures package.
  • This abstraction layer on top of Python's threading and multiprocessing modules offers the interface for completing operations using a pool of threads or processes. 
  • A process has a greater degree of abstraction than a thread.