argparse
is the best library to use to parse command-line arguments in Python. It is included in Python standard libaries (which menas that you can use it out of the box).It is suggestedd that you always log a parsed Namespace object so that you can check whether it is as expected.
ArgumentParser.parse_args
takes a list (instead of string) for the parameterargs
! This is due tosys.argv
is of the list type.The
add_parser
function can be used to define subcommands. It takes both ahelp
argument and adescription
argument. Thehelp
argument is for help doc of its parent command while thedescription
argument is for help doc of itself. It is suggested that you pass the same help doc to both arguments. Please refer to /blog.py for such examples.The argument
aliases
does not take a geneartor as input. Generally speaking, you should be carefule about using a generator as a generator is essentially an iterator which is invalidated once iterated. Use a list instead if you have to iterator a collection multiple times.It seems that the default value for an argument must be specified in the first occurrence of the corresponding
add_argument
function.You can check whether an option is defined for a command or not using
'some_option' in args
whereargs
is a Namespace object returned byargparse.parse_args
. For example, you can useargs.level if 'level' in args else 'INFO'
to get the value for the optionargs.level
with the fallback valueINFO
. You can also convert a Namespace object to a dictionary using the functionvars
, so an even easier way of get the value of an option with a fallback value is usevars(args).get('level', 'INFO')
. One thing to notice that if an option belongs to a mutual exclusive group which is required, then it is ALWAYS included in the final parsed Namespace object. In that case, the right way to check whether the option is specified is to check whether it isNone
or not. Please refer to the Mutually Exclusive section for more discussions.Do NOT call time-consuming or likely-to-throw-exception functions/methods when defining default values of command-line options!!! Specially, avoid calling HTTP request to parse information for default values of command-line options. The reason is that default values for options are always calculated no matter it is needed for the (sub)command or not. If a function/method which is time-consuming, or likely to throw exception, or might fail due to firewall is used to define default values of command-line options, it greatly hurts use experience of the command-line tool. A better alternative is to use None, empty string, etc. for the default value and handle it when the corresponding (sub)command is invoked. This delays the computation of the function/method until it is really needed.
Optional Positional Arguments¶
By design,
positional arguments are always required (which is different from options).
However,
you can leverage the nargs
option to achive optional positional arguments.
Basically,
you use nargs=*
to let argparse knwo that the positonal argument takes 0 or more inputs.
from argparse import ArgumentParser, Namespace
parser = ArgumentParser(description="Illustrate an optional positional argument.")
parser.add_argument("numbers", nargs="*", help="A list of numbers.")
parser.parse_args([])
parser.parse_args(["1", "2", "3"])
parser.parse_args("1 2 3")
Convert to dict¶
ns = Namespace(x=1, y=2)
ns
vars(ns)
Convert from dict¶
dic = {"x": 1, "y": 2}
dic
Namespace(**dic)
Mutually Exclusive¶
You can use the method add_mutually_exclusive_group
to define a mutually exclusive group,
i.e.,
only one option in the group can be specified in the command line.
And you use the option required=True
to make the group required,
i.e., one of the options in the group must be specified.
Notice that all options in a REQUIRED
mutually exclusive group are present in the final parsed Namespace.
Those options not specified have a default value None
.
So the right way to check whether an option in a mutually exclusive group is specified
is to check whether it has value other than None
.
That is use the following code
:::bash
if args.some_mutex_opt is not None:
...
instead of
:::bash
if "some_mutex_opt" in args:
...
mutex_group = parser.add_mutually_exclusive_group()
mutex_group = parser.add_mutually_exclusive_group(required=True)
Good Examples of Using argparse¶
https://github.com/dclong/blog/blob/master/main.py
https://github.com/dclong/xinstall/blob/dev/xinstall/main.py