Hello my friend,
Recently we have learned how to use the external modules to make your Python’s code more powerful. At some point, perhaps already now, you started creating user-defined functions so good that you would like to re-use them in other projects.
Automate all the things
Network automation is one of the most important things named by CIOs in Gather’s research. As such, the companies are (and will be) looking for the experts, who are able to develop new solutions and find creative ways to improve networks’ efficiency via automation. And we are keen to help you with that?
At our network automation training, either self-paced or instructor lead, you will learn the leading technologies, protocols, and tools used to manage the networks in the busiest networks worldwide, such as Google data centres. However, once you master all the skills, you will be able to automate the network of any scale. You will see the opportunities and you will exploit them.
Secret words: NETCONF, REST API, gRPC, JSON , XML, Protocol buffers, SSH, OpenConfig, Python, Ansible, Linux, Docker; and many other wonderful tools and techniques are waiting for you in our training!
Don’t miss opportunity to start your network automation training today!
What are we going to do today?
Earlier we have created a scrip, which generates the list of the IP addresses in the provided range. Today we will:
- Convert that code in a user-defined function.
- Place the user-defined function in a separate file in a separate folder.
- Import created module in your code and use it.
All the previous CEX labs are available at your disposal in our GitHub repo.
Besides that you will also revise how to use the external modules.
The lab setup isn’t change. As such, we are constantly using Python 3.8.
Why does it matter?
There are a couple of reasons. First of all, it is just impractical to have a long file with all your helper functions located there. The troubleshooting will be quite a complicated, as you will have to scroll the long listings before you get to the appropriate part.
Second, it is more difficult to track the dependencies between the different functions. As such, it is very easy to get to lean towards the spaghetti code, what you should avoid by all means.
The third point was mentioned above already: if you create some functions, that you believe might be helpful in your other projects, you should split it in a separate file, so that you can refer to them later easily.
How are we doing that?
In the previous session you have learned how to import any artefact from the external module: it can be variables, functions, classes, etc. Exactly in the same way it is working import of any items from the file. Assuming you have the following structure of your files:
1
2
3
4 +--root_folder
+--main.py
+--bin
+--helper.py
And in your helper.py you have some variables or functions:
1
2
3
4
5
6
7
8
9 $ cat bin/helper.py
#!/usr/bin/python
creds = {'username': 'aaa', 'password': 'bbb'}
def user_function(some_var):
result = []
# doing some compute
return result
Then in your script main.py you can import those elements using from … import … (or just import …):
1
2
3
4
5
6 $ cat main.py
#!/usr/bin/python
from bin.helper import creds, user_function
!
! FURTHER OUTPUT IS OMITTED FOR BREVITY
So in this snippet you see that the path is provided is sub_directory.file_name, where:
- sub_directory is the name of the directory
- file_name is the name of your file with Python code. The file name is provided without “.py” extension.
With all this in mind, let’s get started rebuilding our code.
#1. Folders and files structure
First of all, you should think about how your code will be split. You can choose any name for the directories, but one of the most common name for the directory containing your additional Python scripts is called “bin“. The script, which is doing the job is very often named “main.py“, whereas others, which you import, can have virtually any name. As such, for the lab we advise to set the following hierarchy:
1
2
3
4
5 +--CEX
+--13
+--bin
| +--ip_converter.py
+--main.py
#2. User-defined function in a separate file
In the CEX #09 we have created the script, which takes the range of the IP addresses as an input and lists all the IPs in that range. This code is quite good, as, if packed as a user-defined function, it can be used in various scripts (e.g. pinging multiple network elements to verify that they are live). Hence, we will structure it as a user-defined function using the following guidelines:
- The input to the function should be a string in a format first_ip-last_ip.
- The output should a list of the IPs, if the input was accurate. If it wasn’t, then the function should terminate the Python’s code execution with an error.
Refer to the original blogpost to get the understanding of the scripts’ flow.
Based on the guidelines, the function will be like this:
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
46 #!/usr/local/bin/python3.8
# Modules
import sys
# User-defined functions
def get_ip_list(ip_addresses):
result = []
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 += (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 += (int(ip_end[index]) * (256 ** (len(ip_end) - 1 - index)))
index -= 1
if num_ip_s <= num_ip_e:
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 %= (256 ** (3 - ind))
ind += 1
result.append('.'.join(temp_ip_l))
num_ip_t += 1
return result
else:
sys.exit('The starting IP in the range is higher than the final one.')
Let’s take a closer look, what is happening here:
- If the script you are creating requires external modules (like sys in the provided snippet), it shall be part of the script with the user-defined function.
- The function is defined as an ordinary user-defined function; hence, it shall have both incoming vars and return at the end. As such, we have added the Python list named result, which is return in case of successful function’s execution.
#3. Calling external files from your script
After you helper file with the user defined function is complete, you can import it in your main script:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 #!/usr/local/bin/python3.8
# Modules
import sys
from bin.ip_converter import get_ip_list
# Variables
if len(sys.argv) < 3:
target_ips = '10.0.0.3-10.0.1.15'
else:
target_ips = f'{sys.argv[1]}-{sys.argv[2]}'
ip_list = get_ip_list(target_ips)
print(f'Your IPs are: ')
for ip in ip_list:
print(ip)
In this main script we import module sys, as we’d like to provide the arguments to the script upon its launch using argv variable. And, finally, we import from the created file the function get_ip_list, which we have created in the previous point. Afterwards, the script validates that if you provide less than two arguments (overall length is less than three arguments including the script’s name):
- If you do then it takes the default range as a value for the target_ips variable.
- If you don’t then it takes the first and the second variables assign they are the first and the last IP of the provided range and generate the string target_ips based on them.
Using the imported function get_ip_list, the variable ip_list is created and its values are printed.
#4. Verification
Let’s run the Python’s script with the proper arguments:
1
2
3
4
5
6
7
8
9
10
11
12
13 $ ./main.py 192.168.1.10 192.168.1.20
Your IPs are:
192.168.1.10
192.168.1.11
192.168.1.12
192.168.1.13
192.168.1.14
192.168.1.15
192.168.1.16
192.168.1.17
192.168.1.18
192.168.1.19
192.168.1.20
You can also run it without arguments, then the default will be picked up:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 $ ./main.py
Your IPs are:
10.0.0.3
10.0.0.4
10.0.0.5
10.0.0.6
10.0.0.7
10.0.0.8
10.0.0.9
!
! OUTPUT IS TRUNCATED FOR BREVITY
!
10.0.1.13
10.0.1.14
10.0.1.15
If you prefer video
If you more prefer watching the video rather than reading the articles, it is all good. Subscribe to our YouTube channel, where you will find all the latest our videos including previous Code EXpress (CEX) episodes.
And here is the latest one:
What else shall you try?
Learning programming is all about trying and testing. To fully understand what we have covered so far, you can try the following additional scenarios:
- Create a new function inside the created file, which can list the IPv6 addresses in the provided range (or any other function you believe it makes sense to externalise).
- Import it in your main script and use it there.
Lessons at GitHub
The code from this class, like from any other class as well, you can find in our GitHub repository.
Conclusion
Relying on the external code is very common practice . Take care and good bye!
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