To us, Network Engineers, world of coding, developer skills and programmability are becoming a must. No one conceives anymore a network where the administrator or engineers, the NOC, or whoever does day-to-day tasks on it don’t have coding skills, does not know how to code or automates tasks.

So, at this point we all should have at least a basic working knowledge of Python. And we can safely assume we all did some scripts to automate tasks. If these tasks involve multiple devices, then we usually implement loops where we go through the list of devices we want to automate and through the list of commands we want to run, and run them, sequentially.

While this does indeed work, it involves a slow iteration process where we have to finish with one of the devices and then move on to the next one, and so on and so forth. As we all imagine, doing this one by one has a few drawbacks. We have to finish with one device before moving to the next one, which makes it slow. We have to debug failure conditions so in case of failure in one of the iterations, it will continue running with the next one. And some more, but the most critical is time. The more devices we have in our loop, the more time it will take for the entire script to complete.

Have we thought of multithreading yet?

Well, it is the solution. Let’s fire up the command sequence we want to run in each device, in more than one device at once. That will divide the total execution time, and we will hopefully be sipping coffe before we can think of it.

Below you have an example script that runs 3 threads at once in your computer. Each thread does nothing remarkable indeed, but as a thread is perfect for the example. Out thread will log start and finish time, and in between it will sleep for 2 seconds. Time enough to see it running. As we can see we used the concurrent.futures library to trigger the threads by calling ThreadPoolExecutor and mapping the thread function. The rest is easy enough to be uderstood.

There it is:

import logging  
 import time  
 import concurrent.futures  
 def thread_function(name):  
 logging.info("Thread %s: START", name)  
 time.sleep(2)  
 logging.info("Thread %s: FINISH", name)  
 if __name__ == "__main__":  
 format = "%(asctime)s: %(message)s"  
 logging.basicConfig(format=format, level=logging.INFO, datefmt="%H:%M:%S")  
 with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:  
 executor.map(thread_function, range(3))

threads.py

And here we have the output:

user@deb:~$ python3 threads.py
 13:01:05: Thread 0: starting  
 13:01:05: Thread 1: starting  
 13:01:05: Thread 2: starting  
 13:01:07: Thread 0: finishing  
 13:01:07: Thread 2: finishing  
 13:01:07: Thread 1: finishing

output

That’s all. Now you have the easiest way I know to trigger threads and run tasks concurrently. Hope it will help you to save that valuable time!