argparse Command Line Argument Parsing

argparse is a command line argument parser inspired by Python’s “argparse” library. Use this with Rscript to write “#!”-shebang scripts that accept short and long flags/options and positional arguments, generate a usage statement, and set default values for options that are not specified on the command line.

In our working directory we have two example R scripts, named “example.R” and “display_file.R” illustrating the use of the argparse package.

bash$ ls

display_file.R
example.R

In order for a *nix system to recognize a “#!”-shebang line you need to mark the file executable with the chmod command, it also helps to add the directory containing your Rscripts to your path:

bash$ chmod ug+x display_file.R example.R

bash$ display_file.R example.R

Here is what “example.R” contains:

bash$ display_file.R example.R

#!/usr/bin/env Rscript
# Copyright 2012-2013 Trevor L Davis <trevor.l.davis@gmail.com>
# Copyright 2008 Allen Day
#
#  This file is free software: you may copy, redistribute and/or modify it
#  under the terms of the GNU General Public License as published by the
#  Free Software Foundation, either version 2 of the License, or (at your
#  option) any later version.
#
#  This file is distributed in the hope that it will be useful, but
#  WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#  General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
suppressPackageStartupMessages(library("argparse"))

# create parser object
parser <- ArgumentParser()

# specify our desired options
# by default ArgumentParser will add an help option
parser$add_argument(
    "-v",
    "--verbose",
    action = "store_true",
    default = TRUE,
    help = "Print extra output [default]"
)
parser$add_argument(
    "-q",
    "--quietly",
    action = "store_false",
    dest = "verbose",
    help = "Print little output"
)
parser$add_argument(
    "-c",
    "--count",
    type = "integer",
    default = 5,
    help = "Number of random normals to generate [default %(default)s]",
    metavar = "number"
)
parser$add_argument(
    "--generator",
    default = "rnorm",
    help = "Function to generate random deviates [default \"%(default)s\"]"
)
parser$add_argument(
    "--mean",
    default = 0,
    type = "double",
    help = "Mean if generator == \"rnorm\" [default %(default)s]"
)
parser$add_argument(
    "--sd",
    default = 1,
    type = "double",
    metavar = "standard deviation",
    help = "Standard deviation if generator == \"rnorm\" [default %(default)s]"
)

# get command line options, if help option encountered print help and exit,
# otherwise if options not found on command line then set defaults,
args <- parser$parse_args()

# print some progress messages to stderr if "quietly" wasn't requested
if (args$verbose) {
    write("writing some verbose output to standard error...\n", stderr())
}

# do some operations based on user input
if (args$generator == "rnorm") {
    cat(paste(rnorm(args$count, mean = args$mean, sd = args$sd), collapse = "\n"))
} else {
    cat(paste(do.call(args$generator, list(args$count)), collapse = "\n"))
}
cat("\n")

By default argparse will generate a help message if it encounters --help or -h on the command line. Note how %(default)s in the example program was replaced by the actual default values in the help statement that argparse generated.

bash$ example.R –help

usage: example.R [-h] [-v] [-q] [-c number] [--generator GENERATOR] [--mean MEAN] [--sd standard deviation]

options:
  -h, --help            show this help message and exit
  -v, --verbose         Print extra output [default]
  -q, --quietly         Print little output
  -c number, --count number
                        Number of random normals to generate [default 5]
  --generator GENERATOR
                        Function to generate random deviates [default "rnorm"]
  --mean MEAN           Mean if generator == "rnorm" [default 0]
  --sd standard deviation
                        Standard deviation if generator == "rnorm" [default 1]

If you specify default values when creating your ArgumentParser then argparse will use them as expected.

bash$ example.R

writing some verbose output to standard error...

-1.27007527013558
-1.404177922459
-1.16881243149805
1.08898914240976
-0.664239841308519

Or you can specify your own values.

bash$ example.R –mean=10 –sd=10 –count=3

writing some verbose output to standard error...

22.0931200973524
2.65033343471014
17.2196537870774

If you remember from the example program that --quiet had action="store_false" and dest="verbose". This means that --quiet is a switch that turns the verbose option from its default value of TRUE to FALSE. Note how the verbose and quiet options store their value in the exact same variable.

bash$ example.R –quiet -c 4 –generator=“runif”

0.145101793343201
0.769703338388354
0.373955984367058
0.494743616553023

If you specify an illegal flag then will print out a usage message and an error message and quit.

bash$ example.R –silent -m 5

usage: example.R [-h] [-v] [-q] [-c number] [--generator GENERATOR] [--mean MEAN] [--sd standard deviation]
example.R: error: unrecognized arguments: --silent -m 5

If you specify the same option multiple times then will use the value of the last option specified.

bash$ example.R -c 100 -c 2 -c 1000 -c 7

writing some verbose output to standard error...

0.0966196948937709
0.181309664785241
0.409183223624513
-1.93238982399365
0.109687464689486
2.21907553582888
2.03087995497323

argparse can also parse positional arguments. Below we give an example program display_file.R, which is a program that prints out the contents of a single file (the required positional argument, not an optional argument) and which accepts the normal help option as well as an option to add line numbers to the output.

bash$ display_file.R –help

usage: display_file.R [-h] [-n] file

positional arguments:
  file               File to be displayed

options:
  -h, --help         show this help message and exit
  -n, --add_numbers  Print line number at the beginning of each line [default]

bash$ display_file.R –add_numbers display_file.R

1 #!/usr/bin/env Rscript
2 # Copyright 2012-2013 Trevor L Davis <trevor.l.davis@gmail.com>
3 #
4 #  This file is free software: you may copy, redistribute and/or modify it
5 #  under the terms of the GNU General Public License as published by the
6 #  Free Software Foundation, either version 2 of the License, or (at your
7 #  option) any later version.
8 #
9 #  This file is distributed in the hope that it will be useful, but
10 #  WITHOUT ANY WARRANTY; without even the implied warranty of
11 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 #  General Public License for more details.
13 #
14 #  You should have received a copy of the GNU General Public License
15 #  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 suppressPackageStartupMessages(library("argparse"))
17 
18 parser <- ArgumentParser()
19 parser$add_argument(
20  "-n",
21  "--add_numbers",
22  action = "store_true",
23  default = FALSE,
24  help = "Print line number at the beginning of each line [default]"
25 )
26 parser$add_argument("file", nargs = 1, help = "File to be displayed")
27 
28 args <- parser$parse_args()
29 
30 file <- args$file
31 
32 if (file.access(file) == -1) {
33  stop(sprintf("Specified file ( %s ) does not exist", file))
34 } else {
35  file_text <- readLines(file)
36 }
37 
38 if (args$add_numbers) {
39  cat(paste(seq_along(file_text), file_text), sep = "\n")
40 } else {
41  cat(file_text, sep = "\n")
42 }

bash$ display_file.R non_existent_file.txt

Error: Specified file ( non_existent_file.txt ) does not exist
Execution halted

bash$ display_file.R

usage: display_file.R [-h] [-n] file
display_file.R: error: the following arguments are required: file