From a workshop given at the Python User Group, Foundations for Research Computing, Columbia University, on November 3rd, 2020.
- A program should do one thing, and do it well.
- Programs should be interoperable by reading and writing text over standard input and standard output
- Standard input (stdin)
- usually the output from a pipe
- Standard output (stdout)
- usually text printed to the screen
echo "Hello world!"
This program prints “Hello world!” to the screen (to standard output). That output can be piped |
into another program.
echo "Hello world!" | wc -w
Here, the standard output from echo "Hello world!"
is being piped into wc
(word count), which accepts standard input, and returns its word count. It should return 2
.
(CLI is command-line interface.)
This program, shout.py
, takes standard input, uppercases it, and prints it to standard output. So given hello world
it returns HELLO WORLD!
.
import sys
stdin = sys.stdin.read()
print(stdin.upper())
Run it with:
echo "hello world" | python shout.py
And it should return HELLO WORLD
.
Arguments are what come after the program name when you’re calling a program on the command line. So in the command cat file1 file2 file3
, cat
is the name of the command, and file1
, file2
, and file3
are arguments. Here, they correspond to files, and that command prints out the contents of all of those files, concatenated together.
Try this in a file called argv.py:
print(sys.argv)
Then run it with:
python argv.py arg1 arg2 arg3
And you should see ['argv.py', 'arg1', 'arg2', 'arg3']
.
Using sys.argv
, let’s make a weird version of cat
that prints out the contents of files whose filenames are given as arguments, only uppercased.
import sys
for filename in sys.argv:
contents = open(filename).read()
print(contents.upper())
Let’s say we wanted to write a command-line program that, like wc
, gave the user options for how to shout its input. If you run python shout.py
it should shout whatever it’s given (i.e. uppercase it). And if you run python shout.py --loud
, it should add a bunch of exclamation points to the end, making it extra loud.
import sys
import argparse
stdin = sys.stdin.read()
# description will appear as our program's help.
parser = argparse.ArgumentParser(description='Shout it out!')
# action='store_true' says: if this option is present, assign args.loud to True.
# Otherwise assign it to False (the default.)
parser.add_argument('--loud', action='store_true', help='whether to add exclamation points')
args = parser.parse_args()
output = stdin.upper()
if args.loud:
output += '!!!'
print(output)
echo "hello" | python shout.py
# HELLO
echo "hello" | python shout.py --loud
# HELLO!!!
Our program now also has automatically-generated documentation (help) for the user:
echo "hello" | python shout.py --help
Prints:
usage: shout.py [-h] [--loud]
Shout it out!
optional arguments:
-h, --help show this help message and exit
--loud whether to add exclamation points
For more uses of argparse
, see the library’s documentation.