About this page
This is not an introduction to argparse. All we have here is a bunch of recipes that make argparse behave in desired ways. I hope to cover the most commonly used command-line actions.
The “main” program
All the recipes below are assumed to be invoked like this:
def main():
parser = argparse.ArgumentParser(description = 'argparse recipe book')
recipe_xx(parser)
if __name__ == '__main__':
main()
Recipe 01:
Optional flag --kill
Code:
def recipe_01(parser):
"""Optional flag --kill
action='store_true' => no argument expected after --kill
"""
parser.add_argument('--kill', action='store_true', help='Die, die, die!!!')
args = parser.parse_args()
print(args.kill)
Recipe in action:
vnetman:mint:~> ./argparse_recipe_book.py
False
vnetman:mint:~> ./argparse_recipe_book.py -h
usage: argparse_recipe_book.py [-h] [--kill]
argparse recipe book
optional arguments:
-h, --help show this help message and exit
--kill Die, die, die!!!
vnetman:mint:~> ./argparse_recipe_book.py --kill
True
Recipe 02:
--repeat <count>
--repeat is optional; if given, <count> is compulsory
Code:
def recipe_02(parser):
""" --repeat <count>
--repeat is optional; if given, <count> is compulsory
'metavar' is used in the help text
No meaningful help for -r though; see recipe_03 for a better version
Note that there is no 'action = ...' => there is an argument that follows
"""
parser.add_argument('--repeat', metavar='<n>', type=int)
args = parser.parse_args()
print(args.repeat)
Recipe in action:
vnetman:mint:~> ./argparse_recipe_book.py
None
vnetman:mint:~> ./argparse_recipe_book.py --help
usage: argparse_recipe_book.py [-h] [--repeat <n>]
argparse recipe book
optional arguments:
-h, --help show this help message and exit
--repeat <n>
vnetman:mint:~> ./argparse_recipe_book.py --repeat
usage: argparse_recipe_book.py [-h] [--repeat <n>]
argparse_recipe_book.py: error: argument --repeat: expected one argument
vnetman:mint:~> ./argparse_recipe_book.py --repeat 10
10
Recipe 03:
Same as recipe_02, but better help
Code:
def recipe_03(parser):
""" Same as recipe_02, but better help
"""
parser.add_argument('--repeat', metavar='<n>', type=int,
help='how many repeats')
args = parser.parse_args()
print(args.repeat)
Recipe in action:
vnetman:mint:~> ./argparse_recipe_book.py
None
vnetman:mint:~> ./argparse_recipe_book.py --help
usage: argparse_recipe_book.py [-h] [--repeat <n>]
argparse recipe book
optional arguments:
-h, --help show this help message and exit
--repeat <n> how many repeats
vnetman:mint:~> ./argparse_recipe_book.py --repeat
usage: argparse_recipe_book.py [-h] [--repeat <n>]
argparse_recipe_book.py: error: argument --repeat: expected one argument
vnetman:mint:~> ./argparse_recipe_book.py --repeat 10
10
Recipe 04:
--out <filename>
Compulsory argument (i.e. --out is compulsory, and a filename must follow it)
Code:
def recipe_04(parser):
""" --out <filename>
Compulsory argument (i.e. --out is compulsory, and a filename must follow it)
'type=..' unspecified => string is assumed as default
required=True => you guessed it, the argument is compulsory
"""
parser.add_argument('--out', metavar='<file name>',
help='destination file', required=True)
args = parser.parse_args()
print(args.out)
Recipe in action:
vnetman:mint:~> ./argparse_recipe_book.py
usage: argparse_recipe_book.py [-h] --out <file name>
argparse_recipe_book.py: error: the following arguments are required: --out
vnetman:mint:~> ./argparse_recipe_book.py --help
usage: argparse_recipe_book.py [-h] --out <file name>
argparse recipe book
optional arguments:
-h, --help show this help message and exit
--out <file name> where to write
vnetman:mint:~> ./argparse_recipe_book.py --out
usage: argparse_recipe_book.py [-h] --out <file name>
argparse_recipe_book.py: error: argument --out: expected one argument
vnetman:mint:~> ./argparse_recipe_book.py --out foobar
foobar
Recipe 05:
<in-file>
One compulsory argument without any switches
Code:
def recipe_05(parser):
""" <in-file>
One compulsory argument without any switches
"""
parser.add_argument('in_file', metavar='<input-file>',
help='file containing input')
args = parser.parse_args()
print('input file is "' + args.in_file + '"')
Recipe in action:
vnetman:mint:~> ./argparse_recipe_book.py
usage: argparse_recipe_book.py [-h] <input-file>
argparse_recipe_book.py: error: the following arguments are required: <input-file>
vnetman:mint:~> ./argparse_recipe_book.py --help
usage: argparse_recipe_book.py [-h] <input-file>
argparse recipe book
positional arguments:
<input-file> file containing input
optional arguments:
-h, --help show this help message and exit
vnetman:mint:~> ./argparse_recipe_book.py foobar
input file is "foobar"
Recipe 06:
Zero or more arguments without any switches
(See recipe_07 for better-looking help text)
Code:
def recipe_06(parser):
"""Zero or more arguments without any switches
(See recipe_07 for better-looking help text)
"""
parser.add_argument('pcaps', nargs='*')
args = parser.parse_args()
for _ in args.pcaps:
print(_)
Recipe in action:
vnetman:mint:~> ./argparse_recipe_book.py
vnetman:mint:~> ./argparse_recipe_book.py --help
usage: argparse_recipe_book.py [-h] [pcaps [pcaps ...]]
argparse recipe book
positional arguments:
pcaps
optional arguments:
-h, --help show this help message and exit
vnetman:mint:~> ./argparse_recipe_book.py alpha
alpha
vnetman:mint:~> ./argparse_recipe_book.py alpha beta gamma delta epsilon
alpha
beta
gamma
delta
epsilon
vnetman:mint:~>
Recipe 07:
Same as recipe_06, but with a better-looking help text
[<pcap-1> <pcap-2> ...]
Zero or more arguments without any switches
Code:
def recipe_07(parser):
""" Same as recipe_06, but with a better-looking help text
[<pcap-1> <pcap-2> ...]
Zero or more arguments without any switches
"""
parser.add_argument('pcaps', nargs='*', metavar='<pcap-file>',
help='input pcap file for streams')
args = parser.parse_args()
for _ in args.pcaps:
print(_)
Recipe in action:
vnetman:mint:~> ./argparse_recipe_book.py
vnetman:mint:~> ./argparse_recipe_book.py --help
usage: argparse_recipe_book.py [-h] [<pcap-file> [<pcap-file> ...]]
argparse recipe book
positional arguments:
<pcap-file> input pcap file for streams
optional arguments:
-h, --help show this help message and exit
vnetman:mint:~> ./argparse_recipe_book.py mercury venus earth mars
mercury
venus
earth
mars
vnetman:mint:~>
Recipe 08:
<pcap-1> [<pcap-2> ...]
One or more arguments without any switches
Code:
def recipe_08(parser):
""" <pcap-1> [<pcap-2> ...]
One or more arguments without any switches
Note: nargs = '+' for one or more, '*' for zero or more
"""
parser.add_argument('pcaps', nargs='+', metavar='<pcap-file>',
help='input pcap file for streams')
args = parser.parse_args()
for _ in args.pcaps:
print(_)
Recipe in action:
vnetman:mint:~> ./argparse_recipe_book.py
usage: argparse_recipe_book.py [-h] <pcap-file> [<pcap-file> ...]
argparse_recipe_book.py: error: the following arguments are required: <pcap-file>
vnetman:mint:~> ./argparse_recipe_book.py --help
usage: argparse_recipe_book.py [-h] <pcap-file> [<pcap-file> ...]
argparse recipe book
positional arguments:
<pcap-file> input pcap file for streams
optional arguments:
-h, --help show this help message and exit
vnetman:mint:~> ./argparse_recipe_book.py japan
japan
vnetman:mint:~> ./argparse_recipe_book.py japan korea china
japan
korea
china
Recipe 09:
Optional switch --colors
If given, at least one arg must be provided, possibly more
Code:
def recipe_09(parser):
"""Optional switch --colors
If given, at least one arg must be provided, possibly more
"""
parser.add_argument('--colors', nargs='+')
args = parser.parse_args()
if args.colors:
for _ in args.colors:
print(_)
else:
print('No colors specified')
Recipe in action:
vnetman:mint:~> ./argparse_recipe_book.py
No colors specified
vnetman:mint:~> ./argparse_recipe_book.py --help
usage: argparse_recipe_book.py [-h] [--colors COLORS [COLORS ...]]
argparse recipe book
optional arguments:
-h, --help show this help message and exit
--colors COLORS [COLORS ...]
vnetman:mint:~> ./argparse_recipe_book.py --colors
usage: argparse_recipe_book.py [-h] [--colors COLORS [COLORS ...]]
argparse_recipe_book.py: error: argument --colors: expected at least one argument
vnetman:mint:~> ./argparse_recipe_book.py --colors red
red
vnetman:mint:~> ./argparse_recipe_book.py --colors black brown red orange yellow green blue
black
brown
red
orange
yellow
green
blue
Recipe 10:
<--get | --set | --clear>
Mutually exclusive boolean flags
Any one must be specified
Code:
def recipe_10(parser):
"""<--get | --set | --clear>
Mutually exclusive boolean flags
Any one must be specified
Use 'add_mutually_exclusive_group', and add the arguments to the group\
"""
get_set_clear_group = parser.add_mutually_exclusive_group(required=True)
get_set_clear_group.add_argument('--get', action='store_true',
help='get the available stock quantity')
get_set_clear_group.add_argument('--set', action='store_true',
help='set the available stock quantity')
get_set_clear_group.add_argument('--clear', action='store_true',
help='clear the available stock quantity')
args = parser.parse_args()
print('get = {}, set = {}, clear = {}'.
format(args.get, args.set, args.clear))
Recipe in action:
vnetman:mint:~> ./argparse_recipe_book.py
usage: argparse_recipe_book.py [-h] (--get | --set | --clear)
argparse_recipe_book.py: error: one of the arguments --get --set --clear is required
vnetman:mint:~> ./argparse_recipe_book.py --help
usage: argparse_recipe_book.py [-h] (--get | --set | --clear)
argparse recipe book
optional arguments:
-h, --help show this help message and exit
--get get the available stock quantity
--set set the available stock quantity
--clear clear the available stock quantity
vnetman:mint:~> ./argparse_recipe_book.py --set
get = False, set = True, clear = False
vnetman:mint:~> ./argparse_recipe_book.py --get
get = True, set = False, clear = False
vnetman:mint:~> ./argparse_recipe_book.py --clear
get = False, set = False, clear = True
vnetman:mint:~> ./argparse_recipe_book.py --get --clear
usage: argparse_recipe_book.py [-h] (--get | --set | --clear)
argparse_recipe_book.py: error: argument --clear: not allowed with argument --get
Recipe 11:
--opcode <get | set | clear>
--opcode is mandatory, and must be followed by one of 'get', 'set', or 'clear'
In other words, this is a different approach to achieve the same end behaviour
as recipe_10
Code:
def recipe_11(parser):
"""--opcode <get | set | clear>
--opcode is mandatory, and must be followed by one of 'get', 'set', or 'clear'
In other words, this is a different approach to achieve the same end
behaviour as recipe_10
'choices = ' limits the allowed arguments
remove the 'required = True' if you don't want --opcode to be mandatory
"""
parser.add_argument('--opcode', choices=['get', 'set', 'clear'],
help='desired operation', required=True)
args = parser.parse_args()
print(args.opcode)
Recipe in action:
vnetman:mint:~> ./argparse_recipe_book.py
usage: argparse_recipe_book.py [-h] --opcode {get,set,clear}
argparse_recipe_book.py: error: the following arguments are required: --opcode
vnetman:mint:~> ./argparse_recipe_book.py --help
usage: argparse_recipe_book.py [-h] --opcode {get,set,clear}
argparse recipe book
optional arguments:
-h, --help show this help message and exit
--opcode {get,set,clear}
desired operation
vnetman:mint:~> ./argparse_recipe_book.py --opcode get
get
vnetman:mint:~> ./argparse_recipe_book.py --opcode put
usage: argparse_recipe_book.py [-h] --opcode {get,set,clear}
argparse_recipe_book.py: error: argument --opcode: invalid choice: 'put' (choose from 'get', 'set', 'clear')
vnetman:mint:~> ./argparse_recipe_book.py --opcode get set
usage: argparse_recipe_book.py [-h] --opcode {get,set,clear}
argparse_recipe_book.py: error: unrecognized arguments: set
Recipe 12:
--retries <1-10>
'--retries' is optional. If provided, must be followed by an integer argument from 1 to 10 inclusive.
Code:
def recipe_12(parser):
"""--retries <1-10>
--retries is optional. If provided, must be followed by an integer argument
from 1 to 10 inclusive.
"""
parser.add_argument('--retries', choices=range(1, 11), type=int,
metavar='<attempts (1-10)>',
help='how many times to retry')
args = parser.parse_args()
if args.retries:
print('args.retries is of type "{}", and has value {}'.
format(type(args.retries), args.retries))
else:
print('retries not specified')
Recipe in action:
vnetman:mint:~> ./argparse_recipe_book.py
retries not specified
vnetman:mint:~> ./argparse_recipe_book.py --help
usage: argparse_recipe_book.py [-h] [--retries <attempts 1-10>]
argparse recipe book
optional arguments:
-h, --help show this help message and exit
--retries <attempts (1-10)>
how many times to retry
vnetman:mint:~> ./argparse_recipe_book.py --retries
usage: argparse_recipe_book.py [-h] [--retries <attempts 1-10>]
argparse_recipe_book.py: error: argument --retries: expected one argument
vnetman:mint:~> ./argparse_recipe_book.py --retries 3
args.retries is of type "<class 'int'>", and has value 3
vnetman:mint:~> ./argparse_recipe_book.py --retries 30
usage: argparse_recipe_book.py [-h] [--retries <attempts 1-10>]
argparse_recipe_book.py: error: argument --retries: invalid choice: 30 (choose from 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
vnetman:mint:~> # Note that when a value outside the range is specified, the error message prints out *all* the allowed values. This can be an issue when the range is large.
Recipe 13:
Multiple sub-commands, each with its own set of options
add --name <name> --age <age> --gender (male|female)
view [--males-only | --females-only] [--seniors | --no-seniors]
modify --id <id> --points <delta>
delete --id <id> [--force]
Code:
def recipe_13(parser):
"""Multiple sub-commands, each with its own set of options
add --name <name> --age <age> --gender (male|female)
view [--males-only | --females-only] [--seniors | --no-seniors]
modify --id <id> --points <delta>
delete --id <id> [--force]
"""
# Setting dest='operation' means that the value returned from the final
# parse_args() call will contain an attribute called 'operation', which
# indicates which sub-command (i.e. add/view/modify/delete) was specified on
# the command line.
subparsers = parser.add_subparsers(help='Database record operation',
dest='operation')
subparsers.required = True
parser_op_add = subparsers.add_parser('add', help='Add a new record')
parser_op_view = subparsers.add_parser('view', help='View records')
parser_op_modify = subparsers.add_parser('modify', help='Change a record')
parser_op_delete = subparsers.add_parser('delete', help='Delete a record')
# Options for 'add'
parser_op_add.add_argument('--name', metavar='<name>', required=True)
parser_op_add.add_argument('--age', metavar='<age>', required=True,
type=int)
parser_op_add.add_argument('--gender', required=True,
choices=['male', 'female'])
# Options for 'view'
gender_group = parser_op_view.add_mutually_exclusive_group()
age_group = parser_op_view.add_mutually_exclusive_group()
gender_group.add_argument('--males-only', action='store_true')
gender_group.add_argument('--females-only', action='store_true')
age_group.add_argument('--seniors', action='store_true')
age_group.add_argument('--no-seniors', action='store_true')
# Options for 'modify'
parser_op_modify.add_argument('--id', required=True, type=int,
metavar='<id>')
parser_op_modify.add_argument('--points', required=True, type=int,
metavar='<points>')
# Options for 'delete'
parser_op_delete.add_argument('--id', required=True, type=int,
metavar='<id>')
parser_op_delete.add_argument('--force', action='store_true')
args = parser.parse_args()
# Setting dest='which' in the add_subparsers() invocation above, which means
# that the 'which' attribute of args tells us which sub-command was entered
if args.operation == 'add':
print('Adding name "{}", age "{}", gender "{}"'.
format(args.name, args.age, args.gender))
elif args.operation == 'view':
if args.males_only:
gender_sel = 'only males'
elif args.females_only:
gender_sel = 'only females'
else:
gender_sel = 'all genders'
if args.seniors:
age_sel = 'seniors only'
elif args.no_seniors:
age_sel = 'no seniors'
else:
age_sel = 'all ages'
print('Viewing records for {}, {}'.format(gender_sel, age_sel))
elif args.operation == 'modify':
print('Modifying record for ID {}, points = {}'.
format(args.id, args.points))
elif args.operation == 'delete':
print('Deleting record for ID {}, force = {}'.
format(args.id, args.force))
else:
raise ValueError('invalid operation')
Recipe in action:
vnetman@mint:~/work/argparse_recipe_book$ ./argparse_recipe_book.py
usage: argparse_recipe_book.py [-h] {add,view,modify,delete} ...
argparse_recipe_book.py: error: the following arguments are required: operation
vnetman@mint:~/work/argparse_recipe_book$
vnetman@mint:~/work/argparse_recipe_book$ ./argparse_recipe_book.py -h
usage: argparse_recipe_book.py [-h] {add,view,modify,delete} ...
argparse recipe book
positional arguments:
{add,view,modify,delete}
Database record operation
add Add a new record
view View records
modify Change a record
delete Delete a record
optional arguments:
-h, --help show this help message and exit
vnetman@mint:~/work/argparse_recipe_book$
vnetman@mint:~/work/argparse_recipe_book$ ./argparse_recipe_book.py add
usage: argparse_recipe_book.py add [-h] --name <name> --age <age> --gender {male,female}
argparse_recipe_book.py add: error: the following arguments are required: --name, --age, --gender
vnetman@mint:~/work/argparse_recipe_book$
vnetman@mint:~/work/argparse_recipe_book$ ./argparse_recipe_book.py add --help
usage: argparse_recipe_book.py add [-h] --name <name> --age <age> --gender {male,female}
optional arguments:
-h, --help show this help message and exit
--name <name>
--age <age>
--gender {male,female}
vnetman@mint:~/work/argparse_recipe_book$
vnetman@mint:~/work/argparse_recipe_book$ ./argparse_recipe_book.py view --help
usage: argparse_recipe_book.py view [-h] [--males-only | --females-only] [--seniors | --no-seniors]
optional arguments:
-h, --help show this help message and exit
--males-only
--females-only
--seniors
--no-seniors
vnetman@mint:~/work/argparse_recipe_book$
vnetman@mint:~/work/argparse_recipe_book$ ./argparse_recipe_book.py modify --help
usage: argparse_recipe_book.py modify [-h] --id <id> --points <points>
optional arguments:
-h, --help show this help message and exit
--id <id>
--points <points>
vnetman@mint:~/work/argparse_recipe_book$
vnetman@mint:~/work/argparse_recipe_book$ ./argparse_recipe_book.py delete --help
usage: argparse_recipe_book.py delete [-h] --id <id> [--force]
optional arguments:
-h, --help show this help message and exit
--id <id>
--force
vnetman@mint:~/work/argparse_recipe_book$ ./argparse_recipe_book.py add --name "harry"
usage: argparse_recipe_book.py add [-h] --name <name> --age <age> --gender {male,female}
argparse_recipe_book.py add: error: the following arguments are required: --age, --gender
vnetman@mint:~/work/argparse_recipe_book$ ./argparse_recipe_book.py add --name "harry" --age 12 --gender
usage: argparse_recipe_book.py add [-h] --name <name> --age <age> --gender {male,female}
argparse_recipe_book.py add: error: argument --gender: expected one argument
vnetman@mint:~/work/argparse_recipe_book$ ./argparse_recipe_book.py add --name "harry" --age 12 --gender male
Adding name "harry", age "12", gender "male"
vnetman@mint:~/work/argparse_recipe_book$ ./argparse_recipe_book.py view
Viewing records for all genders, all ages
vnetman@mint:~/work/argparse_recipe_book$ ./argparse_recipe_book.py view --help
usage: argparse_recipe_book.py view [-h] [--males-only | --females-only] [--seniors | --no-seniors]
optional arguments:
-h, --help show this help message and exit
--males-only
--females-only
--seniors
--no-seniors
vnetman@mint:~/work/argparse_recipe_book$ ./argparse_recipe_book.py view --males-only
Viewing records for only males, all ages
vnetman@mint:~/work/argparse_recipe_book$ ./argparse_recipe_book.py modify
usage: argparse_recipe_book.py modify [-h] --id <id> --points <points>
argparse_recipe_book.py modify: error: the following arguments are required: --id, --points
vnetman@mint:~/work/argparse_recipe_book$ ./argparse_recipe_book.py modify --help
usage: argparse_recipe_book.py modify [-h] --id <id> --points <points>
optional arguments:
-h, --help show this help message and exit
--id <id>
--points <points>
vnetman@mint:~/work/argparse_recipe_book$ ./argparse_recipe_book.py modify --id 101
usage: argparse_recipe_book.py modify [-h] --id <id> --points <points>
argparse_recipe_book.py modify: error: the following arguments are required: --points
vnetman@mint:~/work/argparse_recipe_book$ ./argparse_recipe_book.py modify --id 101 --points -20
Modifying record for ID 101, points = -20
vnetman@mint:~/work/argparse_recipe_book$ ./argparse_recipe_book.py remove
usage: argparse_recipe_book.py [-h] {add,view,modify,delete} ...
argparse_recipe_book.py: error: argument operation: invalid choice: 'remove' (choose from 'add', 'view', 'modify', 'delete')
vnetman@mint:~/work/argparse_recipe_book$ ./argparse_recipe_book.py delete
usage: argparse_recipe_book.py delete [-h] --id <id> [--force]
argparse_recipe_book.py delete: error: the following arguments are required: --id
vnetman@mint:~/work/argparse_recipe_book$ ./argparse_recipe_book.py delete --id 101
Deleting record for ID 101, force = False
vnetman@mint:~/work/argparse_recipe_book$ ./argparse_recipe_book.py delete --id 101 --force
Deleting record for ID 101, force = True