Hello my friend,
So far you have learned about the for loop and if conditional. Both of these tools are very useful and have a wide area of the applicability inside the network automation filed. But what if we need to do some activities in your Python code continuously until a certain condition becomes False? The answer you will find in this blogpost.
Network automation training – boost your career
Don’t wait to be kicked out of IT business. Join our network automation training to secure your job in future. Come to NetDevOps side.
How does the training differ from this blog post series? Here you get the basics and learn some programming concepts in general, whereas in the training you get comprehensive set of knowledge with the detailed examples how to use Python for the network and IT automation. You need both.
What are we going to do today?
While loop is a specific type of the loop in Python, which is being executed infinitely while the associated condition is True. All the knowledge you got about the if conditionals are applicable here as well.
Read the if conditional blogpost for more details.
Therefore, while instruction requires careful planing before being used, as it potentially could make your code no working. And today you will learn:
- When it makes sense to use while loop.
- How to use while loop in a real life scenario.
- How to troubleshoot while loops went to infinity
The general logic about the while loop in Python is to use them when that is absolutely necessary, and to use for loop in all other cases. To rephrase it, if you can solve the task using the for loop, go for it rather than going for while loop.
Besides the while loop, you will also learn how to use the most popular math operations in Python.
As usual, all the explanation is based on the Python 3.8 version.
If you want to know how to install Python 3.8, check the corresponding blogpost.
Why does it matter?
Some tasks within the network automation need to be done multiple times, without knowing how many times at the point, when their execution starts. The example we are going to cover today is the listing all the IP addresses out of certain range. The range could be as small as a single IP, or as huge as all the IPv4 or IPv6 addresses. Therefore, the Python script doesn’t know, how many iterations it should do in order to list all these IP addresses. In the same way, from the task it is obvious you need to list all the IPs, so you need to increment a number going from the lowest number in the range to the biggest. Comparing the iterated IP with the target allows you create a flexible loop, where while fits perfectly.
Another often example is the work with the REST API, where you need to collect the information from a certain network controller. If this is a production environment, it might be often the case that you need to make multiple requests to collect the information, as it will be too much information to do that in a single request. Using while loop allows you to perform as many requests as necessary in order to collect all the available information without knowing in advance how many requests you actually need.
As you can see, the general area of the while loop application is when you need to do certain tasks multiple times, but in advance you don’t know how many.
How are we doing that?
Following the approach, we have started earlier, we create a new directory in our GitHub Python’s lessons:
1
2
3
4 $ cd CEX
$ mkdir 09
$ cd 09
$
Inside the directory we create a new file called while.py, which we will use during this class:
1
2
3 $ touch while.py && chmod a+x while.py
$ cat while.py
#!/usr/local/bin/python3.8
If you have a question to chmod command or to the path to the Python interpreter, take a look on the corresponding class .
Before we kick off with the Python’s script development, let’s take a look on the syntax:
1
2 while condition:
actions
- The while loop starts if the condition is True and the actions are executed
- After the last item in actions is executed, the condition is checked again.
- In case it is True, the actions are executed once more. And they will be executed all the time, when the condition is True.
- When the condition becomes False, the while loop is not executed further and the Python script goes further.
Based on the provided explanation, it is imperative to make sure that your condition could be ever False. That means that the actions inside the while loop should be changing something, what affects the condition.
Otherwise, it like an loop in the network: it brings the code down and doesn’t allow it do its job.
#1. Preparing the input
As stated earlier, you will see how you can create a list of IP addresses based on the input range. Let’s prepare this range:
1
2
3
4
5
6
7
8
9 $ cat while.py
#!/usr/local/bin/python3.8
# Variables
ip_addresses = '10.0.0.3-10.0.1.15'
ip_start, ip_end = ip_addresses.split('-')
print('The first IP is {} and the last one is {}'.format(ip_start, ip_end))
Read the corresponding articles for .format() and for .split() functions.
The Python’s code above creates two IP addresses: the beginning and the end of the range. The IP addresses are provided in the dotted-decimal format, like standard for IP addresses. However, from the Python perspective it is just a string.
Let’s check them:
1
2 $ ./while.py
The first IP is 10.0.0.3 and the last one is 10.0.1.15
#2. Using while loop to convert IP address to a single decimal number
As we need to list all the IP addresses in this range using Python code, we need to covert the strings into numbers. And that is where the while loop starts getting useful:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 $ cat while.py
#!/usr/local/bin/python3.8
# Variables
ip_addresses = '10.0.0.3-10.0.1.15'
ip_start, ip_end = ip_addresses.split('-')
ip_start = ip_start.split('.')
index = len(ip_start) - 1
num_ip_s = 0
while index >= 0:
num_ip_s = num_ip_s + (int(ip_start[index]) * (256 ** (len(ip_start) - 1 - index)))
index -= 1
ip_end = ip_end.split('.')
index = len(ip_end) - 1
num_ip_e = 0
while index >= 0:
num_ip_e = num_ip_e + (int(ip_end[index]) * (256 ** (len(ip_end) - 1 - index)))
index -= 1
print('The first IP is {} and the last one is {}'.format(ip_start, ip_end))
print('In decimal format numbers are {} and {}'.format(num_ip_s, num_ip_e))
In the snippet above the following is happening:
- Using the split() functions we transform a string containing the IP address into a Python’s list.
- Using the len() functions we get the amount of the elements inside the generated list. Then we decrease it by one as Python’s list index starts with 0.
- Using while loop we converts the elements inside initial list into a single number using the math.
- Function int() converts the string value to an integer if that is possible.
- The operation -= means that the original value of a variable on the left side (index) is decremented by the number on the right side (1).
- The actions inside the while loop are done 4 times following the index value: 3, 2, 1, 0. Once index becomes -1, the while loop stops.
If you are not familiar with the IP address structure, there is a binary math behind. And the provided computation are based on that math.
The execution of the Python’s script shows you the generated list and the single decimal value associated with the IP address:
1
2
3 $ ./while.py
The first IP is ['10', '0', '0', '3'] and the last one is ['10', '0', '1', '15']
In decimal format numbers are 167772163 and 167772431
If something is wrong in your code and the condition stays always True for while loop, you will see that Python’s code execution doesn’t stop. Press Ctrl+Z to interrupt it.
#3. Adding the if conditional
The logic behind this scenario is to list all the IP addresses starting from the lowest till the highest in the provided range. It can be, though, that by mistake or intentionally the first IP in the range is higher than the last one, what is mistake. To avoid the Python’s code misbehaviour you can add the conditional check using if:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 $ cat ./while.py
#!/usr/local/bin/python3.8
# Variables
ip_addresses = '10.0.0.3-10.0.1.15'
ip_start, ip_end = ip_addresses.split('-')
ip_start = ip_start.split('.')
index = len(ip_start) - 1
num_ip_s = 0
while index >= 0:
num_ip_s = num_ip_s + (int(ip_start[index]) * (256 ** (len(ip_start) - 1 - index)))
index -= 1
ip_end = ip_end.split('.')
index = len(ip_end) - 1
num_ip_e = 0
while index >= 0:
num_ip_e = num_ip_e + (int(ip_end[index]) * (256 ** (len(ip_end) - 1 - index)))
index -= 1
if num_ip_s <= num_ip_e:
print('Printing IP in range {}'.format(ip_addresses))
else:
print('The starting IP in the range is higher than the final one.')
If we run the Python’s code as we have it now, then we get to the proper execution part:
1
2 $ ./while.py
Printing IP in range 10.0.0.3-10.0.1.15
However, if we change the IP range to be not accurate and re-run the Python’s script, we get way different output:
1
2
3
4
5
6
7
8
9
10 $ cat ./while.py
#!/usr/local/bin/python3.8
# Variables
ip_addresses = '10.0.2.3-10.0.1.15'
! Further Python's code is unchanged
$ ./while.py
The starting IP in the range is higher than the final one.
There is one more step to do to list all the IPs. Let’s do it together.
#4. Using nested while loop for sophisticated math operations
To convert the string in doted-decimal format we used the math operations such as addition (+), multiplication (*) and to the power (**). To get the IP out of the integer back, we need to use the revert math functions, such as subtraction (-), division (/) and the rest from the division (%). And we need to do that multiple times, for each IP address. Therefore, your Python 3 code comes to the following form:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 $ cat while.py
#!/usr/local/bin/python3.8
# Variables
ip_addresses = '10.0.0.3-10.0.1.15'
ip_start, ip_end = ip_addresses.split('-')
ip_start = ip_start.split('.')
index = len(ip_start) - 1
num_ip_s = 0
while index >= 0:
num_ip_s = num_ip_s + (int(ip_start[index]) * (256 ** (len(ip_start) - 1 - index)))
index -= 1
ip_end = ip_end.split('.')
index = len(ip_end) - 1
num_ip_e = 0
while index >= 0:
num_ip_e = num_ip_e + (int(ip_end[index]) * (256 ** (len(ip_end) - 1 - index)))
index -= 1
if num_ip_s <= num_ip_e:
print('Printing IP in range {}'.format(ip_addresses))
num_ip_t = num_ip_s
while num_ip_t <= num_ip_e:
decr = num_ip_t
ind = 0
temp_ip_l = []
while decr > 0:
temp_ip_l.append(str(int(decr / 256 ** (3 - ind))))
decr = decr % (256 ** (3 - ind))
ind += 1
print('.'.join(temp_ip_l))
num_ip_t += 1
else:
print('The starting IP in the range is higher than the final one.')
The key idea in the provided snippet is to have a separate variable num_ip_t, which contains the current IP as in integer value. This is IP is incrementing by 1 over the execution of the parent while loop. When the num_ip_t becomes higher than the last IP address in the range based on the input, the while loop stops.
There is also a second while loop, which is nested to the first one. This loop makes the magic of the back conversion of the integer into the string with the dotted-decimal format. Depending on the IP address octet, the division is done by the 256 in the power of the octet index (3, 2, 1, 0) and the Python’s list is appended by the integer part of the division.
Then the variable decr modifies its value with the rest of the division by the 256 in the over of the octet index. This second while loop is executed until decr is more than 0. After that the nested while loop is stopped.
The final Python’s scripts result is the following:
1
2
3
4
5
6
7
8
9
10
11 ]$ ./while.py
Printing IP in range 10.0.0.3-10.0.1.15
10.0.0.3
10.0.0.4
10.0.0.5
10.0.0.6
10.0.0.7
10.0.0.8
! Some output is truncated for brevity
10.0.1.14
10.0.1.15
Here you get the list of IP addresses using the Python while loop, and many other things we’ve covered so far.
If you prefer video
If you prefer watching the video instead of reading blogpost, that is also wonderful. We value your time and want to create for you the best experience possible. Therefore, for all the blogposts associated with CEX series, we will record the video and post it on our YouTube channel.
And here is the video for this blogpost:
What else shall you try?
Programming is all around testing, trying, breaking and fixing the things. Try to do the following things to collect some more experience:
- Rewrite the script in case the initial IP range is provided in the format subnet/prefix (e.g 10.0.0.0/23).
Lessons in GitHub
You can find the final working versions of the files from this blog at our GitHub page.
Conclusion
The while loop extends the toolkit you have in terms of the Python’s code flow control. In case it is applied properly, it can helps you a lot, when you need to continuously making some actions not knowing the amount of iterations in advance. Take care and goodbye!
Support us
P.S.
If you have further questions or you need help with your networks, I’m happy to assist you, just send me message. Also don’t forget to share the article on your social media, if you like it.
BR,
Anton Karneliuk