Development

40 minute read

7 Python Code Examples for Everyday Use

Renato Candido

Renato Candido

As you evolve in your developer career, you improve your collection of tools, libraries and also write some custom command line tools to facilitate your work. 

In this resource, you'll go through some examples of command line tools to use in your day-to-day life as a developer. For each of the examples, you'll begin by implementing a basic version of the tool to understand how it works. Then you'll polish your work, turning it into a more professional command line tool, by including data validation and support to use them with command line arguments. 

So, grab your favorite code editor and get started with some useful Python code examples. 


  1. Getting the list of links from a website
  2. Getting the resolution of an image
  3. Rotating images
  4. Resizing images
  5. Searching for a file
  6. Getting the day of the week from a date
  7. Generating a random password

Coding with GoSkills

1. Getting the list of links from a website 

In this first code example, you're going to build a command line tool to gather all links presented on a given website page. For that, you're going to obtain the HTML code from the website and look for patterns that represent links in this code. 

To obtain the HTML code from a website, you'll need to perform an HTTP request. Python's standard library has some alternatives to perform HTTP requests but most of them are not that easy to use.

Fortunately, there's Requests, a library that implements "HTTP for humans", as said in its documentation page. As it is not part of Python's standard library, you're going to have to install it using pip, by running the following command:

pip install requests

To implement a command line tool that is useful in day-to-day life, you'll have to consider some aspects such as input validation and the use of command line arguments. However, before going into these details, it's important to begin with the simplest implementation possible, as shown next:

import requests
import re
 
url = input("Enter the URL: ")
 
html = requests.get(url).text
 
links = re.findall('"(https?://.*?)"', html)
 
for link in links:
    print(link)

Here you're using requests to get the HTML from the website and re to process the HTML and look for the links in the HTML code. 

The re package implements functions to work with regular expressions, which allows you to look for patterns in text, being widely used for data analysis applications. 

A URL is obtained by user input and stored in the url variable. Then, requests.get(url).text is used to perform a request to the URL and get the HTML from the response. 

Next, you use re.findall to look for link patterns in the HTML text. The string "(https?://.*?)" represents the regular expression you're looking for in the text. Keep in mind that "(https?://.*?)" represents links, starting with http:// or https:// that are inside double quotes in the HTML retrieved. 

All the results that match the regular expression are stored in the links list. This way, you just have to iterate over it and print its contents to get a list of links contained in the HTML, as done in the for loop. Try saving the program as get_urls.py and running it. You should get something like the following:

$ python get_urls.py
Enter the URL: http://www.goskills.com
https://cdn.goskills.com/assets/favicon/apple-touch-icon.png?v=1
https://cdn.goskills.com/assets/favicon/favicon-32x32.png?v=1
https://cdn.goskills.com/assets/favicon/favicon-16x16.png?v=1
https://cdn.goskills.com/assets/favicon/site.webmanifest?v=1
https://cdn.goskills.com/assets/favicon/safari-pinned-tab.svg?v=1
https://cdn.goskills.com/assets/favicon/favicon.ico?v=1
https://cdn.goskills.com/assets/favicon/browserconfig.xml?v=1
https://cdn.goskills.com
https://connect.facebook.net
https://www.google-analytics.com
https://stats.g.doubleclick.com
https://cdn.goskills.com/assets/fonts/icons/goskills-icons.woff2?1.25
https://cdn.goskills.com/assets/fonts/open-sans/v17-latin-ext/open-sans-300.woff2
https://cdn.goskills.com/assets/fonts/open-sans/v17-latin-ext/open-sans-400.woff2
https://cdn.goskills.com/assets/fonts/open-sans/v17-latin-ext/open-sans-400i.woff2
(...)

Now that you have a basic implementation working, it will be interesting to make some improvements to turn it into a useful command line tool. You'll begin by validating the user input to not allow an empty URL, with the following code:

import requests
import re
 
while True:
    url = input("Enter the URL: ")
 
    if url == "":
        print("Invalid URL")
        continue
    break
 
html = requests.get(url).text
 
links = re.findall('"(https?://.*?)"', html)
 
for link in links:
    print(link)

This is a possible way of validating the user data, obtained with the input() function. Here, a while loop is used to keep asking the user until a non empty URL is provided. Save the changes to get_urls.py and try to run it to see the validation scheme working. 

Although the validation considers just a "non empty" test in this case, you could extend the structure to consider more sophisticated data validation by changing the condition of the if block. 

Finally, it's important to add the possibility to run the command using command line arguments, so that you could use it providing the URL directly from the command line. For that, you can rely on Argparse, a module from Python's standard library that makes it easy to write user-friendly command-line interfaces, as shown in the following code:

import requests
import re
import argparse
 
parser = argparse.ArgumentParser(
    description="Get list of links from a website"
)
 
parser.add_argument("url", nargs="?", help="URL", default=None)
 
arguments = parser.parse_args()
 
use_arguments = True if arguments.url is not None else False
 
# Check whether url will be obtained from command line argument
# or from user input
if use_arguments:
    url = arguments.url
else:
    while True:
        url = input("Enter the URL: ")
 
        if url == "":
            print("Invalid URL")
            continue
        break
 
html = requests.get(url).text
 
links = re.findall('"(https?://.*?)"', html)
 
for link in links:
    print(link)

To use Argparse, you need first to import the module, which is done with import argparse. Then, you need to configure it, which basically consists of three steps: 

  1. Instantiate an ArgumentParser object that will receive the information of the command line arguments you want to use, and parse them to retrieve the information provided by the user via command line. Here, this is done with the parser object. 
  2. Configure the command line arguments you are going to use. Here, only one argument is considered, named url. Notice the argument is created with nargs="?" and default=None, which makes this argument not required and defaults it to None in case it is not provided. This is useful to check if the program is used in command line mode or in interactive mode, as you'll see later. 
  3. Parse the arguments and retrieve them, so that you can use the information on your code. This is done by the line arguments = parser.parse_args(). 

To indicate whether command line mode or interactive mode is being used, the use_arguments variable is created. It is a boolean variable that is True if the program is being used with command line arguments. To compute it, you use arguments.url, which defaults to None in case no arguments are provided. 

Using the use_arguments variable, you can control whether to get the URL from the command line argument or from the user input, as implemented in the if block. Notice that, in case the program is used in command line mode, you don't need to check for an empty value. The simple fact of having a URL from a command line argument indicates that it is not empty. 

By using Argparse, you get a very nice command line interface, including help messages, defined during setup. Try saving the changes to get_urls.py and run it with python get_urls.py --help. You'll get the following output:

$ python get_urls.py --help
usage: get_urls.py [-h] [url]
 
Get list of links from a website
 
positional arguments:
  url         URL
 
optional arguments:
  -h, --help  show this help message and exit

As you can see, Argparse allows you to build professional command line interfaces in an easy way. Now you can input the URL via command line. For example, you could run:

python get_urls.py http://www.goskills.com

Now that you've gone through the basics of validating inputs and building command line interfaces, you'll build some examples to work with images.  


Interested in programming?

Learn all about it in our comprehensive (and free) ebook!


2. Getting the resolution of an image 

In this example, you're going to build a command line tool to obtain the resolution of an image. For that, you are going to use the Pillow library, which allows you to perform several tasks related to image processing. As Pillow is not part of Python's standard library, you'll have to install it using pip, by running the following command:

pip install pillow

After the installation finishes, you can start developing a simple version of the tool with the following code:

from PIL import Image
 
image = input("Enter the image file name: ")
im = Image.open(image)
print('Image resolution is (w, h): ' + str(im.size))

Just like in the previous example, this first implementation is meant to be the simplest one, without input validation or the use of command line arguments. 

Here, you're importing the Image module from Pillow. Note that the library is named PIL for compatibility reasons with a previous library that was discontinued. In the sequel, you obtain a file name from user input and open the image using Image.open()

Finally, you use the .size() method to obtain the resolution of the image and output a friendly message with this information. 

Try saving the program as resolution_image.py, run it, and input an image file name to see it working. By using the following image, named lenna.png, you should get the result shown next:


Lenna original

lenna.png


$ python resolution_image.py 
Enter the image file name: lenna.png
Image resolution is (w, h): (512, 512)

Now it's time for you to add input validation and support for command line arguments to the program. In this example, you are going to validate the user input and check if it is indeed an image. For that, you can rely on Pillow, which will produce an error when you try to open a file that is not an image, as implemented in the following code:

from PIL import Image
import argparse
import sys
 
parser = argparse.ArgumentParser(description="Print the resolution of an image")
 
parser.add_argument("image", nargs="?", help="Image", default=None)
 
arguments = parser.parse_args()
 
use_arguments = True if arguments.image is not None else False
 
while True:
    if use_arguments:
        image = arguments.image
    else:
        image = input("Enter the image file name: ")
 
    try:
        im = Image.open(image)
    except:
        print('Invalid image')
        if use_arguments:
            sys.exit()
        continue
    break
 
print('Image resolution is (w, h): ' + str(im.size))

The structure is very similar to the one you've used in the previous example. After importing the libraries, you've configured the command line argument parser details. In this case, only one argument named image is being used. 

You'll use the variable use_arguments to check whether the program is being used in command line arguments or in interactive mode, just like you did in the previous example. 

In the while block, things start to get a bit different from the previous example. Recall that, besides validating the interactive input, you'll also validate the command line argument in this case. That's why the while loop was created before the if statement. 

Of course, there are other ways to implement this. Nevertheless, implementing the while loop this way allows you to use only one validation block for both situations, the interactive user input and the command line argument. 

Inside the while loop, there's an if statement to create the image variable, with the image name from the interactive user input or from the command line argument, according to use_arguments

Next, comes the validation block. You're using a try … except block, that allows you to run a code block and perform some action in case it causes some error. In this case, you're trying to load the image with Image.open(). In case an error occurs (for example, if the file name provided by the user does not refer to an image) you show an error message. 

Notice that, when the program is run using command line arguments, after showing the error message, the program exits, since it reaches sys.exit(). On the other hand, when the program is run interactively, the condition in the if block is false and the loop restarts, due to the continue statement. 

Go ahead and test the code. Save the changes to resolution_image.py and try to run it, either interactively or using the command line arguments as in the following:

python resolution_image.py lenna.png

Now that you had your first contact with Pillow, you'll build some other image processing command line tools for your collection.

3. Rotating images 

In this example, you're going to use Pillow again, this time to build a command line tool to perform rotation of images. So, before you begin, make sure you have installed Pillow by running pip install pillow

Like you did in the previous examples, start with a simple implementation, by running the following code:

from PIL import Image
 
image = input("Enter the image file name: ")
angle = input("Enter the rotation angle in degrees: ")
angle = float(angle)
im = Image.open(image)
im_rotate = im.rotate(angle, expand=True)
im_rotate.save("rotated_" + image)

As you can see, this code is very similar to the one used in the beginning of the previous example. Nevertheless, besides getting the image file name, you also get the rotation angle, interactively, from user input. 

As input() returns strings, you need to convert angle to float, in order to be able to use it with Pillow, to perform the image rotation. 

Next, you open the image like the previous example and then perform a rotation using the .rotate() method, saving the result to the im_rotate object. 

Finally, you save the result stored in im_rotate as a new image, with a file named as the original name prefixed by rotated_

Try saving the code as rotate_image.py and then run it inputting lenna.png used in the previous example, to perform a rotation of 60 degrees:

python rotate_image.py
Enter the image file name: lenna.png
Enter the rotation angle: 60

Lenna original

lenna.png (original)


Lenna rotate

rotated_lenna.png


As in the previous examples, now you'll add input validation and support for command line arguments to the program. In this case, you are going to need to validate two inputs: the file name and the angle. For that, you could use the following code:

from PIL import Image
import argparse
import sys
 
parser = argparse.ArgumentParser(description="Rotate an image")
 
parser.add_argument("image", nargs="?", help="Image", default=None)
parser.add_argument("angle", nargs="?", type=float, help="Angle", default=None)
 
arguments = parser.parse_args()
 
use_arguments_image = True if arguments.image is not None else False
use_arguments_angle = True if arguments.angle is not None else False
 
# Validation for image file name
while True:
    if use_arguments_image:
        image = arguments.image
    else:
        image = input("Enter the image file name: ")
 
    try:
        im = Image.open(image)
    except:
        print("Invalid image")
        if use_arguments_image:
            sys.exit()
        continue
    break
 
# Validation for angle
if use_arguments_angle:
    angle = arguments.angle
else:
    while True:
        angle = input("Enter the rotation angle in degrees: ")
 
        try:
            angle = float(angle)
        except:
            print("Invalid angle")
            continue
        break
 
im_rotate = im.rotate(angle, expand=True)
im_rotate.save("rotated_" + image)

Again, notice the code is very similar to the one used in the previous example. The main difference is that you're using two user inputs instead of one. That's why you're using some structures twice: 

  • parser.add_argument() is used to include "image" and "angle" command line arguments. Note that when including the "angle" command line argument, you're using type=float so that you don't need to worry with validation as Argparse performs it for you. 
  • Instead of use_arguments, you are using two variables named use_arguments_image and use_arguments_angle to indicate if each of the arguments is being provided via command line. The user could provide only the image name as a command line argument and, in this case, the program would ask for the angle interactively. 
  • There is a separate block to perform the validation of each argument. The while loop is used to validate the image file name and the if block is used to validate the angle. 

You can see that the while loop used to validate the image file name is identical to the one used in the previous example. 

However, the validation of angle is performed a bit differently. Note that the while loop is created inside the if statement in this case. That's because you don't need to validate the angle in case it was provided as a command line argument. You just need to care about the interactive case, since you've added the argument using type=float when you defined the argument "angle" with parser.add_argument()

Try saving the changes to rotate_image.py and running it, either interactively or using the command line arguments as in the following:

python rotate_image.py lenna.png 60

Then, try to run it providing only the file name:

python rotate_image.py lenna.png

To test the validation provided by Argparse, try to run it providing an invalid angle value. You should get the following:

$ python rotate_image.py lenna.png text
usage: rotate_image.py [-h] [image] [angle]
rotate_image.py: error: argument angle: invalid float value: 'text'

Now that you’ve seen how to deal with multiple arguments, you'll complete your image manipulation toolset by implementing a resizing tool. 

4. Resizing images 

In this example, you'll complete your image manipulation toolset by implementing a resizing tool. For that, you are going to use Pillow again. So, make sure you have installed it by running pip install pillow

Besides that, you're going to use the techniques presented in the previous examples. So make sure you go through them to get details about the implementation before trying this example. 

As usual, you'll start with a simple implementation just to see how Pillow is used to perform image resizing. For that, consider the following code:

from PIL import Image
 
image = input("Enter the image file name: ")
width = input("Enter the new width: ")
height = input("Enter the new height: ")
im = Image.open(image)
width = int(width)
height = int(height)
im_resize = im.resize((width, height), resample=Image.BICUBIC)
im_resize.save("resized_" + image)

If you compare this code to the one used in the beginning of the previous example, you'll notice they are very similar. The main differences are the following: 

  • Here you are considering three arguments: image, width, and height
  • Since width and height should be integer values, you convert them using int()
  • To perform the resize of the image, you use the method .resize(), which receives a tuple to define the new dimension in the form (width, height). The argument resample=Image.BICUBIC defines the algorithm used to calculate the values of the pixels in the resized image. 
  • After performing the resize, you save the new image with the file name prefixed by resized_

Try saving the code as resize_image.py and run it inputting lenna.png (used in the previous example) to resize it to a new image with 256 pixels (width) and 128 pixels (height):

$ python resize_image.py
Enter the image file name: lenna.png
Enter the new width: 256
Enter the new height: 128

Lenna original

lenna.png (original)


Lenna resized

resized_lenna.png


Now, you'll complete the program, adding input validation and support for command line arguments, with the following code:

from PIL import Image
import argparse
import sys
 
parser = argparse.ArgumentParser(description="Resize an image")
 
parser.add_argument("image", nargs="?", help="Image", default=None)
parser.add_argument("width", nargs="?", type=int, help="Width", default=None)
parser.add_argument("height", nargs="?", type=int, help="Height", default=None)
 
arguments = parser.parse_args()
 
use_arguments_image = True if arguments.image is not None else False
use_arguments_width = True if arguments.width is not None else False
use_arguments_height = True if arguments.height is not None else False
 
# Validation for image file name
while True:
    if use_arguments_image:
        image = arguments.image
    else:
        image = input("Enter the image file name: ")
 
    try:
        im = Image.open(image)
    except:
        print("Invalid image")
        if use_arguments_image:
            sys.exit()
        continue
    break
 
# Validation for width
if use_arguments_width:
    width = arguments.width
else:
    while True:
        print("Current resolution is (w, h): " + str(im.size))
        width = input("Enter the new width: ")
        try:
            width = int(width)
        except:
            print("Invalid width")
            continue
        break
 
# Validation for height
if use_arguments_height:
    height = arguments.height
else:
    while True:
        print("Current resolution is (w, h): " + str(im.size))
        height = input("Enter the new height: ")
        try:
            height = int(height)
        except:
            print("Invalid height")
            continue
        break
 
im_resize = im.resize((width, height), resample=Image.BICUBIC)
im_resize.save("resized_" + image)

Notice this program is very similar to the one used in the previous example. The differences are the following: 

  • You're using three arguments to get the image file name, the width, and the height that will be used to create the new image. 
  • As the width and height have to be integer values, you add these arguments on Argparse using type=int, so that you don't have to care about the validation of them in case they are used as command line arguments. 
  • Instead of two validation blocks, here you are using three. Note that the validation block for the image file name is identical while the ones for validating the width and the height are similar to the one used to validate the angle in the previous example. 

Save the changes to resize_image.py and run it to test the validations, either interactively or using the command line arguments. Here are some tests you could perform: 

python resize_image.py lenna.png 256 128
python resize_image.py lenna.png 256
python resize_image.py lenna.png
python resize_image.py

You may also test the validation performed by Argparse, providing some invalid inputs:

python resize_image.py lenna.png text1 text2

That's a good start for some command line tools to work with images. To improve your tool collection, take a look at the Pillow library. It includes several image manipulation algorithms that could be turned into useful command line tools. 

Now, you'll see how to work with default values for arguments in your command line tools. For that, you'll build a file searching tool. 


GoSkills development courses


5. Searching for a file 

In this example, you'll build a file searching tool using the Pathlib module. As a simple implementation, you can use the following code:

from pathlib import Path
 
file_name = input("Filename: ")
folder = "."
folder_answer = input("Folder path (leave empty for the current folder): ")
if folder_answer:
    folder = folder_answer
 
for path in Path(folder).rglob(file_name):
    print(path.absolute())

You begin by importing Path from pathlib module. Then, you get the file name to search from user input. You also get the folder in which the search will be performed. In this case, the default value "." is considered when the user input is empty, which represents the current folder. 

Finally, you use the .rglob() method to search for a file name pattern in the folder specified by folder. As rglob() returns a list of path objects, to print all occurrences, you iterate on the list using a for loop. For each item of the list, the absolute path is obtained using the .absolute() method and printed as output. 

Try saving the program as find_file.py and perform a search. Note that you can use wildcards when inputting the file name. The output should be like the following:

python find_file.py                         
Filename: find_file.py
Folder path (leave empty for the current folder): 
/home/user/src/find_file.py

Now, add input validation and support for command line arguments with the following code:

from pathlib import Path
import argparse
 
parser = argparse.ArgumentParser(description="Find file in file system")
 
parser.add_argument(
    "file_name", nargs="?", help="File name (can use wildcards such as *)",
    default=None
)
parser.add_argument(
    "folder", nargs="?", help="Folder (default: current)",
    default=None
)
 
arguments = parser.parse_args()
 
use_arguments_file_name = True if arguments.file_name is not None else False
use_arguments_folder = True if arguments.folder is not None else False
 
# Validation of file name
if use_arguments_file_name:
    file_name = arguments.file_name
else:
    while True:
        file_name = input("Filename: ")
 
        if file_name == "":
            print("Invalid file name")
            continue
        break
 
# Processing of the folder argument
folder = "."
if use_arguments_folder:
    folder = arguments.folder
else:
    folder_answer = input("Folder path (leave empty for the current folder): ")
    if folder_answer:
        folder = folder_answer
 
for path in Path(folder).rglob(file_name):
    print(path.absolute())

As you can see, this code is a bit simpler than the one from the previous example, as it uses only two arguments: the file name and the folder in which the program will perform the search. 

As you've done before, the file name is validated to not allow an empty value when the program is run in interactive mode. 

The difference here is the processing of the folder argument. As you can see, it does not use any validation but it considers a default value. When a command line argument for folder is not used, it will ask the user for the folder interactively and, in case of an empty response, it will consider the value ".", which represents the current folder. 

Go ahead and save the changes to find_file.py and run it to test the use of the default value. Here are some tests you may try:

python find_file.py file_name /home/user/folder
python find_file.py file_name

In the next example, you'll see an example involving the processing of dates. 

6. Getting the day of the week from a date 

In this example, you're going to build a command line tool to return the day of the week, given a date. For that, you're going to use the Datetime module, which is in Python's standard library. As usual, begin with a simple implementation with the following code:

from datetime import date
 
date_input = input("Enter the date (mm/dd/yyyy): ")
 
date_list = date_input.split("/")
month = int(date_list[0])
day = int(date_list[1])
year = int(date_list[2])
date_date = date(year, month, day)
 
n_day_of_week = date_date.weekday()
 
days_of_week = (
    "Monday",
    "Tuesday",
    "Wednesday",
    "Thursday",
    "Friday",
    "Saturday",
    "Sunday",
)
 
day_of_week = days_of_week[n_day_of_week]
print(day_of_week)

In this example, you use datetime.date to perform the processing and obtain the day of the week for a given date. This way, you begin by importing it with from datetime import date

Next, you get a date from the user in the format mm/dd/yyyy and perform some string manipulations to separate the integer numbers for the month, day, and year. With these numbers, you instantiate a date object named date_date

With the date object date_date, all you need to do to get the day of the week is to call the .weekday() method. It returns an integer from 0 to 6, where 0 represents Monday and 6 represents Sunday, which is stored in the variable n_day_of_week

To convert this result to the actual name of the day, you define a tuple of strings called days_of_week in which the indexes from 0 to 6 contain the values from "Monday" to "Sunday", so that you just need to call days_of_week[n_day_of_week] in order to get the name of the day. Finally, you print the string according to the day of the week. 

Try saving the program as day_of_week.py and run it. The output should be like the following:

python day_of_week.py 
Enter the date (mm/dd/yyyy): 01/01/2020
Wednesday

Now, it's time to complete the program, adding input validation and support for command line arguments. In this case, you're going to validate the date, whether the program is run interactively or via command line arguments, just like you've done with the image file name argument on the previous examples. For that, you can use the following code:

import argparse
import sys
from datetime import date
 
parser = argparse.ArgumentParser(description="Get day of the week from a date")
 
parser.add_argument("date", nargs="?", help="Date (mm/dd/yyyy)", default=None)
 
arguments = parser.parse_args()
 
use_arguments = True if arguments.date is not None else False
 
while True:
    if use_arguments:
        date_input = arguments.date
    else:
        date_input = input("Enter the date (mm/dd/yyyy): ")
 
    try:
        date_list = date_input.split("/")
        month = int(date_list[0])
        day = int(date_list[1])
        year = int(date_list[2])
 
        date_date = date(year, month, day)
    except:
        print("Invalid date")
        if use_arguments:
            sys.exit()
        continue
 
    break
 
n_day_of_week = date_date.weekday()
 
days_of_week = (
    "Monday",
    "Tuesday",
    "Wednesday",
    "Thursday",
    "Friday",
    "Saturday",
    "Sunday",
)
 
day_of_week = days_of_week[n_day_of_week]
print(day_of_week)

By this time, if you've gone through every example, the structure of this program may be familiar to you. After importing the libraries, you set up Argparse, configuring only one argument, named date in this case. 

The while loop is used to keep asking for the date until the user provides a valid one when the program is run interactively. 

When the program is run using a command line argument, use_arguments is True, date_input is obtained via the command line argument, and the loop is stopped by calling sys.exit(), in case the date in invalid. 

Save the changes to day_of_week.py and run it to see it working. Here are some tests you may try:

python day_of_week.py 01/01/2020
python day_of_week.py invalid_date

In the previous examples, you've worked with arguments and several cases of validation. Besides the positional arguments like the ones you've seen, Argparse can also be used to work with optional arguments, which is what you'll see in the next example. 

7. Generating a random password 

In this final example, you'll build a random password generator. The program will take the desired password length and whether or not to use digits or special characters in the password. It will output a random sequence of characters to be used as a password. 

To understand the main logic of the program, consider the simple implementation shown next:

import random
import string
 
use_digits_answer = input("Use digits [y]/n: ")
if use_digits_answer.lower() == "n":
    use_digits = False
else:
    use_digits = True
 
use_punctuation_answer = input("Use special characters [y]/n: ")
if use_punctuation_answer.lower() == "n":
    use_punctuation = False
else:
    use_punctuation = True
 
password_length_answer = input("Length of the password [10]: ")
if password_length_answer == "":
    password_length = 10
else:
    password_length = int(password_length_answer)
 
letters = string.ascii_letters
digits = string.digits
punctuation = string.punctuation
 
symbols = letters
if use_digits:
    symbols += digits
if use_punctuation:
    symbols += punctuation
 
password = "".join(random.choice(symbols) for i in range(password_length))
print(password)

In this program, after importing the libraries, you are getting three inputs from user: 

  • Whether or not to use digits in the password, stored in the binary variable use_digits, which defaults to True, in case the user leaves this answer blank. 
  • Whether or not to use special characters in the password, stored in the binary variable use_punctuation, which defaults to True, in case the user leaves this answer blank. 
  • The length of the password, stored in the variable password_length, which defaults 10, in case the user leaves this answer blank. 

Then, a list of possible symbols named symbols is constructed, based on the information provided. That is, including digits or not and including special characters or not. 

Finally, using this list of symbols, you randomly draw one symbol for each of the characters of the password and join them in a string named password, which is printed as output. 

Save the file as gen_password.py and try to generate a password. You should get an output similar to the following:

python gen_password.py
Use digits [y]/n: 
Use special characters [y]/n: 
Length of the password [10]: 
6iJx/%J#hq

Now, following the same sequence used in the previous examples, you'll implement input validation and support to command line arguments. 

In this example, there are two arguments that have binary values: whether or not to use digits and whether or not to use special characters. For this kind of information, you could use optional command line arguments, those of the type --argument-name

When using optional command line arguments with binary values, you can adopt a default value and use the argument to signalize the other one. For example, you can make the program use digits in the passwords by default and use the argument --no-digits to inform the user not to use digits. 

Using this logic, the complete version of the program can be implemented using the following code:

import random
import string
import argparse
 
parser = argparse.ArgumentParser(description="Password generator")
 
parser.add_argument(
    "--no-digits",
    help="generate password without digits",
    action="store_true"
)
 
parser.add_argument(
    "--no-special-chars",
    help="generate password without special characters",
    action="store_true",
)
 
parser.add_argument(
    "length", nargs="?", type=int, help="length of the password", default=None
)
 
arguments = parser.parse_args()
 
use_arguments = True if (arguments.length or
                         arguments.no_digits or
                         arguments.no_special_chars) else False
use_arguments_length = True if arguments.length else False
 
# Process whether or not to use digits
if use_arguments:
    use_digits = not arguments.no_digits
else:
    while True:
        use_digits_answer = input("Use digits [y]/n: ")
        if use_digits_answer.lower() not in ["", "y", "n"]:
            print("Invalid answer")
            continue
        break
 
    if use_digits_answer.lower() == "n":
        use_digits = False
    else:
        use_digits = True
 
# Process whether or not to use special characters
if use_arguments:
    use_punctuation = not arguments.no_special_chars
else:
    while True:
        use_punctuation_answer = input("Use special characters [y]/n: ")
        if use_punctuation_answer.lower() not in ["", "y", "n"]:
            print("Invalid answer")
            continue
        break
 
    if use_punctuation_answer.lower() == "n":
        use_punctuation = False
    else:
        use_punctuation = True
 
# Process the password length
if use_arguments_length:
    password_length = arguments.length
else:
    while True:
        password_length_answer = input("Length of the password [10]: ")
        if password_length_answer == "":
            password_length = 10            
            break
        else:
            try:
                password_length = int(password_length_answer)
            except:
                print("Invalid value")
                continue
            break
 
letters = string.ascii_letters
digits = string.digits
punctuation = string.punctuation
 
symbols = letters
if use_digits:
    symbols += digits
if use_punctuation:
    symbols += punctuation
 
password = "".join(random.choice(symbols) for i in range(password_length))
print(password)

After importing the libraries, you are setting up Argparse, considering three arguments: 

  • The optional argument --no-digits, to signalize that the password should not include digits 
  • The optional argument --no-special-chars, to signalize that the password should not include special characters 
  • The positional argument length, to define the length of the password. 

Note that when defining the optional arguments, you are using action=store_true which stores True when the argument is used and False, when it is not used. 

The idea in this program is that when it is run without any arguments, it should ask for the three types of information interactively. When it is run with any command line argument, the program should ask only for the password length, when it is not provided. 

To implement this behavior, you create two control variables: 

  • use_arguments, which stores True if any command line argument is used. 
  • use_arguments_length, which stores True if the password length is passed as a command line argument. 

In the sequel, you use three blocks to process each of the inputs. You check use_arguments to control whether use_digits and use_punctuation will be obtained interactively or via command line arguments. Next, you check use_arguments_length to control whether to obtain the length of the password interactively or via command line argument. 

Notice that, when the program is run interactively, you validate the binary inputs by checking if they are equal to "y", "n", or an empty value, which indicates the default value will be used. 

Finally, you generate the password and output it. 

Now, save the changes to gen_password.py and try to run the program to see it working. You can test several ways of inputting the arguments, like the following:

python gen_password.py 15
python gen_password.py --no-digits 15
python gen_password.py --no-digits --no-special-chars 15

Conclusion

In this article, you've gone through the implementation of python code examples as command line tools for everyday use. You've seen Argparse is very handy to implement several kinds of command line tools. It allows you to build them with nice help messages and can also perform validation for the arguments. 

Now that you've learned the basics of implementing them, go ahead and improve your collection by implementing some other useful tools! 

Try our Introduction to Python and Python Data Analysis courses today to learn more about programming with Python.

GoSkills development courses

Loved this? Subscribe, and join 253,468 others.

Get our latest content before everyone else. Unsubscribe whenever.

Renato Candido

Renato Candido

Renato is a technical consultant and researcher in digital signal processing, machine learning, data science, and IoT systems. He teaches in engineering and technology courses and is an enthusiast of {free, libre, open source} {software, hardware, culture, science}.

No comments

LoginSign up