Multi Threading in Python using ‘Activity’ Application

Surya Teja
writearobot
Published in
3 min readApr 23, 2018
Photo by Rosie Kerr on Unsplash

Threads in computer world are described as simple executors (which execute the given instructions). These are light weight and used to perform tasks asynchronously.

Eg: Different tabs in browser act as different threads

In general, At OS level, threads have their own resources but at abstract level they uses same code, data and files.

Source: https://www.studytonight.com

Multi threading in activity application:

Activity is an application developed by my good friend Arijit. It performs bulk server command execution and validations over ssh asynchronously.

It was developed in python 3.6. The core concept of this module is that, it uses multi threading to perform command execution in parallel on all the given servers because of which it consumes less time and performs tasks in an organised and efficient way.

To understand multi threading, Lets dive into some code which is part of activity app, which performs ping check on all the hosts asynchronously.

Ping check function

The above defined function is a callable function, which performs the required activity.

Threads initialization

To understand this we should know a brief background of how parallel execution works in python.

concurrent.futures — Launching parallel tasks

The concurrent.futures module provides a high-level interface for asynchronously executing callables which is a In-built module.

In our program, _ping_single(args): is a executing callable function

The asynchronous execution can be performed using threads and processes. Sub function for threads in concurrent.futures is ThreadPoolExecutor and processes is ProcessPoolExecutor.

To import required module

from concurrent.futures import ThreadPoolExecutor, as_completed

Once imported,

with ThreadPoolExecutor(max_workers=PARALLEL_LIMIT) as pool:

The above line is used to initialize the threads. It is initialized with `with`, so that when execution of a threads complete, the resources of the thread are freed and then shutdown the Executor.

futures = [pool.submit(_ping_single, [h ,self.user, self.reportid]) for h in self.hosts]

The execution starts once the callable function is submitted along with arguments as shown above. In the above line hosts, as well as required arguments are submitted along with callable function.

We can use pool.map to submit the tasks to threads, The difference would be seen in while capturing the output.

for f in as_completed(futures):
output.append(f.result())

Once the threads execution is started, we can capture the output using as_completed or wait function.

The as_completed() function takes an iterable of Future objects and starts yielding values as soon as the futures (threads) start resolving. The main difference between the aforementioned map method with as_completed is that map returns the results in the order in which we pass the iterables. That is the first result from the map method is the result for the first item. On the other hand, the first result from the as_completed function is from whichever future completed first.

The wait() function would return a named tuple which contains two set — one set contains the futures which completed (either got result or exception) and the other set containing the ones which didn’t complete.

Note:

If the threads are not configured properly, There will be performance issues like deadlock, memory leaks.

Conclusion:

Multi threading if configured properly, is an efficient and organized way to reduce the time taken for execution as well improve performance of the program.

For more explanation on multithreading please refer the below article: https://medium.com/@bfortuner/python-multithreading-vs-multiprocessing-73072ce5600b

Source:

--

--