In [1]:
name = '2016-03-04-argument-parsing'
title = 'Argument parsing'
tags = 'argparse, command line'
author = 'Denis Sergeev'
In [2]:
from nb_tools import connect_notebook_to_post
from IPython.core.display import HTML
html = connect_notebook_to_post(name, title, tags, author)
When you use a Python script in command line, you probably have some parameters or input variables set up in the beginning of the script. So you script can look like this:
In [3]:
# Parameters:
a = 1
b = '/path/to/file'
c = True
# The actual script
# ...
Every time you want to execute the program with a different set of parameters, you have to open the script in a text editor, change the necessary lines, save and run it again. Not very effective.
Another way of doing this is to pass parameters as arguments of the script. You can think of it as if your script is a standard system command, such as ls
. Without arguments it displays the contents of the current directory. It also has positional and optional arguments. If you run ls
on a different directory that you currently are in, you would type ls directory_name
, where directory_name
is a positional argument, which means
that the program knows what to do with the value. If you want to display the help text of the ls
command, you would type ls --help
.
To give a python script the same functionality, you can use several built-in libraries.
The simplest way of passing arguments to a python script can be done with sys.argv
. This is just a list of strings and it contains all the values passed in, separated by whitespace. The first argument is the name of the script itself. Let's have a look.
# test.py contents
import sys
print('Arguments:', sys.argv[:])
$ python test.py 123 blabla 1-2
Arguments: ['test.py', '123', 'blabla', '1-2']
Then, the elements of sys.argv
can be assigned to different parameters of your script. This method is not convenient, because the arguments are all strings, so you have to convert them to a required type. You also have to remember the order of the arguments. These two problems make this approach ineffective and prone to errors.
Luckily, python has a module that makes working with arguments a lot more pleasant. The essential piece of code needed to start using argparse
is the following:
# test2.py contents
import argparse # import the module
parser = argparse.ArgumentParser() # create parser instance
parser.parse_args() # parse arguments
This short script already has a 'help' option available (not very useful at this point):
$ python test2.py --help
usage: test2.py [-h]
optional arguments:
-h, --help show this help message and exit
Once you initialised the parser
, you can add rules for different arguments. Note that unless you specify so, you can't pass any number of arguments, unlike in sys.argv
case.
Let's try to add a positional (required) argument to the script and print its value.
# test2.py contents
import argparse # import the module
parser = argparse.ArgumentParser() # create parser instance
parser.add_argument('foo')
args = parser.parse_args() # parse arguments and store them in variable args
print('This is a positional argument:', args.foo)
Run the script:
$ python test2.py 123
This is a positional argument: 123
Now the script requires exactly 1 argument and raises an error if you supply it with other number of arguments.
You can also make rules for your script to have optional arguments. By default, an argument is considered to be optional if its flag in parser.add_argument()
function starts with dashes (usually, 1 dash for a short name and 2 dashes for long name).
For example:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--verbose', help='print optional argument')
args = parser.parse_args()
if args.verbose:
print('The optional argument value is', args.verbose)
which gives the following output if the flag with its value is present:
$ python test.py --verbose 2
The optional argument value is 2
But it also can be run without the flag, and that does not print out anything in this case. Note that you can also customize help messages.
This is just a quick peek at the argparse
features, and there is much more. You can specify type of arguments, number of arguments, True/False arguments, mutually exclusive arguments, file types, default values, choices and so on. There are enough capabilities to build a sophisticated and user-friendly command-line program.
In [4]:
HTML(html)
Out[4]: