Python Package – “argparse”

Hello all,

Today, we will discuss our first package in Python Series for Network Engineers i.e. “argparse”.

Primary questions answered are

  • Why to Use it? – The argparse module makes it easy to write user-friendly command-line interfaces.
  • Why I like to use it so much?

To demonstrate this, We will begin with a simple program (not simple though if it is your first python program) for DNS look up. As all of us are aware, DNS converts “IP Address” to “FQDN (Fully Qualified Domain Name)” and vice versa.

This is how my setup looks like

  1. Domain name: example.com
  2. DNS server (dns @ 192.168.100.100)
  3. Two Hosts (pc2 @ 192.168.1.2 & pc3 @ 192.168.1.3)

Below is the output I received for DNS lookup.

PS C:\Users\gaagrawal> nslookup
Default Server:  dns.example.com
Address:  192.168.100.100

> 192.168.1.2
Server:  dns.example.com
Address:  192.168.100.100

Name:    pc2.example.com
Address:  192.168.1.2

> pc3.example.com
Server:  dns.example.com
Address:  192.168.100.100

Name:    pc3.example.com
Address:  192.168.1.3

In Linux, when you run the “ls” command without any options, it will default displaying the contents of the current directory If you run “ls” on a different directory that you currently are in, you would type “ls directory_name”. The “directory_name” is a “positional argument”, which means that the program know what to do with the value. To get more information about a file we can use the “-l” switch. The “-l” is known as an “optional argument” If you want to display the help text of the ls command, you would type “ls –help”. Hence we are trying to achieve something similar with “argparse”.

Let us start with a program without using “argparse” –

import socket

# Let us demonstrate this without "argparse"
ip_address = '192.168.1.2'
host_name = 'pc3.example.com'

HOSTNAME = socket.gethostbyaddr(ip_address)
ADDRESS = socket.gethostbyname(host_name)
print(HOSTNAME[0], ADDRESS)

Kindly ignore the “socket” package and respective methods at the moment. These will be discussed in more details at the later section. Let’s execute this – we shall receive the corresponding output;

(base) C:\Users\gaagrawal\Desktop\Learn_Python>python dns_lookup_positional.py
pc2.example.com 192.168.1.3

So, the problem with this approach is we have to edit this program every time there is a change in Input which is practically impossible if we have to use this script for thousands of host.

Therefore, It would be great and beneficial – if there was an option to provide such input arguments at the execution of this program. This is all possible with the help of “argparse” package.

Let’s take a look at this program (i.e. demonstrate “argparse” package) –

import socket
import argparse

# Creating a Parser
PARSER = argparse.ArgumentParser(description='Process Command Line')
# The ArgumentParser object will hold all the information 
# necessary to parse the command line into Python data types

# Adding Arguments
PARSER.add_argument('ip_address', type=str, help='IP Address of host')
PARSER.add_argument('host_name', type=str, help='Host Name of host')

# Parsing Arguments
arguments = PARSER.parse_args()

HOSTNAME = socket.gethostbyaddr(arguments.ip_address)
ADDRESS = socket.gethostbyname(arguments.host_name)

print(HOSTNAME[0], ADDRESS)

When we execute this with the given arguments – it works as expected.

$ python dns_lookup_positional.py 192.168.1.2 pc3.example.com
pc2.example.com 192.168.1.3

But again, there is some problem with this? – It is very difficult to understand these positional arguments i.e. we cannot be sure on which Argument should be written first (until and unless you have written this program) i.e. “IP Address” or “Host Name”. What will happen if I swap these input arguments – It will not work. Because, the logic expects “IP Address” as its 1st positional Argument and “Host Name” as  2nd.  

$ python dns_lookup_positional.py pc3.example.com 192.168.1.2
pc3.example.com 192.168.1.2

To verify the order of positional arguments – we can execute this command on our python console.
The --help option, which can also be shortened to -h, is the only option we get for free (i.e. no need to specify it). Specifying anything else results in an error. But even then, we do get a useful usage message, also for free.

$ python dns_lookup_positional.py -h
usage: dns_lookup_positional.py [-h] ip_address host_name

Process Command Line

positional arguments:
  ip_address  IP Address of host
  host_name   Host Name of host

optional arguments:
  -h, --help  show this help message and exit

Hence, positional arguments are not the best way to use in a professional environment. Let’s take a look at the below program which uses optional argument.

import socket
import argparse

# Creating a Parser
PARSER = argparse.ArgumentParser(description='Process Command Line')
# The ArgumentParser object will hold all the information necessary to parse the command line
# into Python data types

# Adding Arguments
# Metavar flag is used just to make --help menu look better
# We have used "-H" instead of "-h" because -h is reserved for Help
PARSER.add_argument('-i','--ip_address', metavar='',type=str, required='TRUE',help='IP Address of host')
PARSER.add_argument('-H','--host_name', metavar='',type=str, required='TRUE',help='Host Name of host')

# Parsing Arguments
arguments = PARSER.parse_args()

HOSTNAME = socket.gethostbyaddr(arguments.ip_address)
ADDRESS = socket.gethostbyname(arguments.host_name)
print(HOSTNAME[0], ADDRESS)

To verify all the changes in this execution – execute as below

$ python dns_lookup_optional.py -h
usage: dns_lookup_optional.py [-h] -i  -H

Process Command Line

optional arguments:
  -h, --help          show this help message and exit
  -i , --ip_address   IP Address of host
  -H , --host_name    Host Name of host

Now, irrespective of where you keep your arguments position. Program will execute and result in same output.

$ python dns_lookup_optional.py -i 192.168.1.2 -H pc3.example.com 
pc2.example.com 192.168.1.3

$ python dns_lookup_optional.py -H pc3.example.com -i 192.168.1.2  
pc2.example.com 192.168.1.3

Hope it clarifies “argparse” package. Refer to complete python programs

# Lets understand the purpose of "argparse" package
# Primary Goals
#       1. Reading Arguments
#       2. Understanding Positional Arguments
# Our objective is to create a Python program name "dns_lookup_positional" which accept two input
#       1. IP ADDRESS
#       2. HOST NAME (FQDN)
# & output must be a Corresponding lookups
# Hence,
#      program name : dns_lookup_positional
# For a moment please forget about the method and library used at the moment;
# These will be discussed in more details in sequential manner

import socket
# Let us demonstrate this without "argparse"
# ip_address = '192.168.1.2'
# host_name = 'pc3.example.com'
#
# HOSTNAME = socket.gethostbyaddr(ip_address)
# ADDRESS = socket.gethostbyname(host_name)
# print(HOSTNAME[0], ADDRESS)

import argparse

# Creating a Parser
PARSER = argparse.ArgumentParser(description='Process Command Line')
# The ArgumentParser object will hold all the information necessary to parse the command line
# into Python data types

# Adding Arguments
PARSER.add_argument('ip_address', type=str, help='IP Address of host')
PARSER.add_argument('host_name', type=str, help='Host Name of host')

# Parsing Arguments
arguments = PARSER.parse_args()

HOSTNAME = socket.gethostbyaddr(arguments.ip_address)
ADDRESS = socket.gethostbyname(arguments.host_name)
print(HOSTNAME[0], ADDRESS)
# Lets understand the purpose of "argparse" package
# Primary Goals
#       1. Reading Arguments
#       2. Understanding Optional Arguments
# Our objective is to create a Python program name "dns_lookup_optional" which accept two input
#       1. IP ADDRESS
#       2. HOST NAME (FQDN)
# & output must results to a Corresponding lookups.
# Hence,
#      program name : dns_lookup_optional
# Let me demonstrate this without using "argparse"
# For a moment please forget about the method and library used at the moment;
# These will be discussed in more details in later section

import socket
import argparse

# Creating a Parser
PARSER = argparse.ArgumentParser(description='Process Command Line')
# The ArgumentParser object will hold all the information necessary to parse the command line
# into Python data types

# Adding Arguments
# Metavar flag is used just to make --help menu look better
# We have used "-H" instead of "-h" because -h is reserved for Help
PARSER.add_argument('-i','--ip_address', metavar='',type=str, required='TRUE',help='IP Address of host')
PARSER.add_argument('-H','--host_name', metavar='',type=str, required='TRUE',help='Host Name of host')

# Parsing Arguments
arguments = PARSER.parse_args()

HOSTNAME = socket.gethostbyaddr(arguments.ip_address)
ADDRESS = socket.gethostbyname(arguments.host_name)
print(HOSTNAME[0], ADDRESS)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.