Here’s how to program in Python – Part 10


Until now we taught you how to program, but we did not teach you how to write a program. The difference? You do programming for yourself; write a program for someone else. You want a user to be able to easily call up a program with options, see a nice result and also request help if he does not know how to use your program. We see all of that in this last Python lesson.

In this tenth lesson we will gradually conclude. Until now you learned all kinds of aspects of it Python and we bring them all together in this lesson. At the end of this lesson, you will have a program that you can run at the command line that handles arguments, issues errors, and displays text in color.

Arguments on the command line

In lesson 3 you already learned to request input from the user with the function input. And although we ran our program there in Thonny, we already mentioned there that you can also run the program in Windows, Linux or macOS on the command line with:

python3 name of program.py

But we expect command line programs to be able to pass arguments to them as well, such as DIR / s in Windows or ls -R in Linux and macOS. How do we ensure that our own programs can do that? Fortunately, Python has a solution for this with the module argparse in the standard library. In this lesson, we will write a program that includes the module palindrome from Lesson 6 to check words for a palindrome, and we are going to give some arguments to that program.

Add arguments

First, we want the program to tell us if a word we pass as an argument to the program is a palindrome. It looks like this:

from argparse import ArgumentParser

from palindrome import is_palindrome

parser = ArgumentParser (description = ‘Determine if a word is a palindrome.’)

parser.add_argument (“–w”, “–word”, required = True, help = “The word you want to check if it is a palindrome”)

args = parser.parse_args ()

result = is_palindrome (args.word)

if result:

print (“The word ‘{}’ is a palindrome.”. format (args.word))

else:

print (“The word ‘{}’ is not a palindrome.”. format (args.word))

You can see that working with argparse is not that difficult. You make one first ArgumentParserobject with the description of your program. Then you add an argument (in our case in a short version -w and a long version –word) and read with parser.parse_args () the arguments entered by the user on the command line. The content of the argument –word is then found in the variable args.word.

Lots of functionality

Now run the program:

$ python3 palindroomchecker.py -w parterretrap

The word ‘parterretrap’ is a palindrome.

$ python3 palindroomchecker.py -w parterretrak

The word ‘parterretrak’ is not a palindrome.

Note: we get a lot of functionality ‘free’ because argparse does it for us. For example, you will receive an error message if you after -w do not specify a word or if you run the program without the argument -w (because we added the argument with required = True). And we also get the argument –Help there for free. If you specify this, the program will show the description of your program and any arguments you have defined:

$ python3 palindroomchecker.py -w

usage: palindroomchecker.py [-h] -w WORD

palindroomchecker.py: error: argument -w / – word: expected one argument

$ python3 palindroomchecker.py

usage: palindroomchecker.py [-h] -w WORD

palindroomchecker.py: error: the following arguments are required: -w / – word

$ python3 palindroomchecker.py –help

usage: palindroomchecker.py [-h] -w WORD

Determine if a word is a palindrome.

optional arguments:

-h, –help

-w WORD, –word WORD

The word for which you want to check whether it is a

palindrome

Arguments that are mutually exclusive

We now want to extend the program so that you can also run the palindrome test one by one on all lines in a text file. Before that we add the argument -b to. But it makes no sense to have both -w as -b at the same time, so we must be able to indicate that both arguments are mutually exclusive. That too is easy with argparse:

parser = ArgumentParser (description = ‘Determine if a word is a palindrome.’)

source = parser.add_mutually_exclusive_group (required = True)

source.add_argument (“–w”, “–word”, help = “The word you want to check if it is a palindrome”)

source.add_argument (“- b”, “–file”, help = “The file containing words you want to check if they are a palindrome”)

args = parser.parse_args ()

With parser.add_mutually_exclusive_group we create a group of arguments that are mutually exclusive. With required = True from that method, we say that the user must use exactly one of the arguments from the group. Then we add our arguments to that group instead of the object parser.

Now if we check if a word is a palindrome and split the display of the result into a separate function show_result (we’ll leave that up to you as an exercise), we can easily handle both instances of input (a word on the command line or words in a file whose name you pass on the command line):

if args word:

show_result (args.word)

else:

with open (args.file, ‘rt’) as file:

for line in file:

show_result (line.strip ())

Try this out. You will see that your program will return an error if you do not provide either or both arguments.

In color

You can also add colors to the output of your program. We use the package for that coloramathat you first have to do with pip3 (see previous lesson) because it is not part of the standard Python library. We import some functions from the module and then initialize colorama:

from colorama import init, Fore, Back, Style

init ()

Then you can play with the foreground color, background color and brightness of the text:

print (Fore.RED + ‘Red text …’)

print (Back.GREEN + ‘… with a green background.’)

print (Style.RESET_ALL + Fore.RED + Style.DIM + ‘Dof …’)

print (Fore.GREEN + Style.BRIGHT + ‘… or clear.’)

print (Style.RESET_ALL)

print (‘And now back to normal!’)

Always add this line at the end of your program:

deinit ()

It resets the output, so that the command line is not suddenly completely red after running your program because you forgot to reset the foreground color!

Optional arguments

We will only use those colors in our palindrome checker if you have an optional argument –color to your program. We add such an optional argument as follows:

parser.add_argument (“–k”, “–color”, action = “store_true”, help = “Show the requested word in color”)

In our program we can then test for the presence of the optional argument with if args color:. We then replace the if-else block from our original program with the following nested structure:

if result:

if args color:

palindrome = Fore.GREEN + Style.BRIGHT + args.word + Style.RESET_ALL

else:

palindrome = args.word

print (“The word ‘{}’ is a palindrome.”. format (palindrome))

else:

if args color:

no_palindrome = Fore.RED + Style.DIM + args.word + Style.RESET_ALL

else:

no_palindrome = args.word

print (“The word ‘{}’ is not a palindrome.”. format (no_palindrome))

Handling errors

Now if you’re in our program that’s the argument -b for a file supports passing a filename that is not supported, our program aborts with the following error message and then the filename:

FileNotFoundError: [Errno 2] No such file or directory:

In addition, you will also see the line of code where it goes wrong. For a user who doesn’t know anything about Python, that’s pretty intimidating. So we’re going to have a try-catch block that handles exception (see lesson 5) and shows a more user-friendly error message.

Before we do that, you need to know something else. Windows, Linux and macOS have three ‘virtual files’ that are important on the command line: stdin (the input from the keyboard), stdout (the normal output of the program) and stderr (the error output of the program). By default we show the output with print stdout, but with file = sys.stderr we redirect the error output to stderr. It will look like this (don’t forget the line import sys at the beginning of your program):

if args word:

show_result (args.word)

else:

try:

with open (args.file, ‘rt’) as file:

for line in file:

show_result (line.strip ())

except FileNotFoundError as error:

print (‘File {} not found’. format (error.filename), file = sys.stderr)

So we try to open the file here. If that doesn’t work, we’ll catch an exception FileNotFoundError off. Note: with except FileNotFoundError as error: we assign the exception to the variable error so that we can get useful information from this object. In this case, it is the filename concerned (error.filename). We show this in the error message to the user, so that he can check why the file does not exist.

The notifications we put on stderr will also appear in the command line like other text that you display with print. But the difference is important. For example, other programs can fix your error messages stderr Filter out.

Resume

In this lesson, you learned how to develop a full Python script that you can run on the command line. You can handle arguments and give errors and you know how to use color in your program. With that we conclude this series of lessons. You are now ready to write your own Python programs!

Order

Add an optional ‘silent’ argument to your program that only outputs if the requested word is a palindrome, so you can quickly find palindromes in large files.

Elaboration

You simply add the optional argument as follows:

parser.add_argument (“- s”, “–stil”, action = “store_true”, help = “Display the requested word if it is a palindrome; display nothing if it is not a palindrome.”)

Then we define the function show_result as follows:

def show_result (word):

result = is_palindrome (word)

if result:

if args.stil:

print (word)

else:

print (“The word ‘{}’ is a palindrome.”. format (word))

else:

if not args.stil:

print (“The word ‘{}’ is not a palindrome.”. format (word))

In this function, we sequentially check whether the word is and palindrome and whether the user entered the optional argument ‘silent’. If we have a palindrome and the program runs silently, we only show the palindrome. If we have a palindrome and the program does not work silently, we will say in a whole sentence that it is a palindrome. If we don’t have a palindrome and the program runs silently, we don’t show anything. And if we do not have a palindrome and the program does not run silently, we are saying in a whole sentence that it is not a palindrome.

Cheat sheet

Stderr: The error output of a program

Stdout: The normal output of a program

.

Recent Articles

Related Stories