17db96d56Sopenharmony_ci.. _argparse-tutorial:
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_ci*****************
47db96d56Sopenharmony_ciArgparse Tutorial
57db96d56Sopenharmony_ci*****************
67db96d56Sopenharmony_ci
77db96d56Sopenharmony_ci:author: Tshepang Lekhonkhobe
87db96d56Sopenharmony_ci
97db96d56Sopenharmony_ci.. currentmodule:: argparse
107db96d56Sopenharmony_ci
117db96d56Sopenharmony_ciThis tutorial is intended to be a gentle introduction to :mod:`argparse`, the
127db96d56Sopenharmony_cirecommended command-line parsing module in the Python standard library.
137db96d56Sopenharmony_ci
147db96d56Sopenharmony_ci.. note::
157db96d56Sopenharmony_ci
167db96d56Sopenharmony_ci   There are two other modules that fulfill the same task, namely
177db96d56Sopenharmony_ci   :mod:`getopt` (an equivalent for ``getopt()`` from the C
187db96d56Sopenharmony_ci   language) and the deprecated :mod:`optparse`.
197db96d56Sopenharmony_ci   Note also that :mod:`argparse` is based on :mod:`optparse`,
207db96d56Sopenharmony_ci   and therefore very similar in terms of usage.
217db96d56Sopenharmony_ci
227db96d56Sopenharmony_ci
237db96d56Sopenharmony_ciConcepts
247db96d56Sopenharmony_ci========
257db96d56Sopenharmony_ci
267db96d56Sopenharmony_ciLet's show the sort of functionality that we are going to explore in this
277db96d56Sopenharmony_ciintroductory tutorial by making use of the :command:`ls` command:
287db96d56Sopenharmony_ci
297db96d56Sopenharmony_ci.. code-block:: shell-session
307db96d56Sopenharmony_ci
317db96d56Sopenharmony_ci   $ ls
327db96d56Sopenharmony_ci   cpython  devguide  prog.py  pypy  rm-unused-function.patch
337db96d56Sopenharmony_ci   $ ls pypy
347db96d56Sopenharmony_ci   ctypes_configure  demo  dotviewer  include  lib_pypy  lib-python ...
357db96d56Sopenharmony_ci   $ ls -l
367db96d56Sopenharmony_ci   total 20
377db96d56Sopenharmony_ci   drwxr-xr-x 19 wena wena 4096 Feb 18 18:51 cpython
387db96d56Sopenharmony_ci   drwxr-xr-x  4 wena wena 4096 Feb  8 12:04 devguide
397db96d56Sopenharmony_ci   -rwxr-xr-x  1 wena wena  535 Feb 19 00:05 prog.py
407db96d56Sopenharmony_ci   drwxr-xr-x 14 wena wena 4096 Feb  7 00:59 pypy
417db96d56Sopenharmony_ci   -rw-r--r--  1 wena wena  741 Feb 18 01:01 rm-unused-function.patch
427db96d56Sopenharmony_ci   $ ls --help
437db96d56Sopenharmony_ci   Usage: ls [OPTION]... [FILE]...
447db96d56Sopenharmony_ci   List information about the FILEs (the current directory by default).
457db96d56Sopenharmony_ci   Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.
467db96d56Sopenharmony_ci   ...
477db96d56Sopenharmony_ci
487db96d56Sopenharmony_ciA few concepts we can learn from the four commands:
497db96d56Sopenharmony_ci
507db96d56Sopenharmony_ci* The :command:`ls` command is useful when run without any options at all. It defaults
517db96d56Sopenharmony_ci  to displaying the contents of the current directory.
527db96d56Sopenharmony_ci
537db96d56Sopenharmony_ci* If we want beyond what it provides by default, we tell it a bit more. In
547db96d56Sopenharmony_ci  this case, we want it to display a different directory, ``pypy``.
557db96d56Sopenharmony_ci  What we did is specify what is known as a positional argument. It's named so
567db96d56Sopenharmony_ci  because the program should know what to do with the value, solely based on
577db96d56Sopenharmony_ci  where it appears on the command line. This concept is more relevant
587db96d56Sopenharmony_ci  to a command like :command:`cp`, whose most basic usage is ``cp SRC DEST``.
597db96d56Sopenharmony_ci  The first position is *what you want copied,* and the second
607db96d56Sopenharmony_ci  position is *where you want it copied to*.
617db96d56Sopenharmony_ci
627db96d56Sopenharmony_ci* Now, say we want to change behaviour of the program. In our example,
637db96d56Sopenharmony_ci  we display more info for each file instead of just showing the file names.
647db96d56Sopenharmony_ci  The ``-l`` in that case is known as an optional argument.
657db96d56Sopenharmony_ci
667db96d56Sopenharmony_ci* That's a snippet of the help text. It's very useful in that you can
677db96d56Sopenharmony_ci  come across a program you have never used before, and can figure out
687db96d56Sopenharmony_ci  how it works simply by reading its help text.
697db96d56Sopenharmony_ci
707db96d56Sopenharmony_ci
717db96d56Sopenharmony_ciThe basics
727db96d56Sopenharmony_ci==========
737db96d56Sopenharmony_ci
747db96d56Sopenharmony_ciLet us start with a very simple example which does (almost) nothing::
757db96d56Sopenharmony_ci
767db96d56Sopenharmony_ci   import argparse
777db96d56Sopenharmony_ci   parser = argparse.ArgumentParser()
787db96d56Sopenharmony_ci   parser.parse_args()
797db96d56Sopenharmony_ci
807db96d56Sopenharmony_ciFollowing is a result of running the code:
817db96d56Sopenharmony_ci
827db96d56Sopenharmony_ci.. code-block:: shell-session
837db96d56Sopenharmony_ci
847db96d56Sopenharmony_ci   $ python3 prog.py
857db96d56Sopenharmony_ci   $ python3 prog.py --help
867db96d56Sopenharmony_ci   usage: prog.py [-h]
877db96d56Sopenharmony_ci
887db96d56Sopenharmony_ci   options:
897db96d56Sopenharmony_ci     -h, --help  show this help message and exit
907db96d56Sopenharmony_ci   $ python3 prog.py --verbose
917db96d56Sopenharmony_ci   usage: prog.py [-h]
927db96d56Sopenharmony_ci   prog.py: error: unrecognized arguments: --verbose
937db96d56Sopenharmony_ci   $ python3 prog.py foo
947db96d56Sopenharmony_ci   usage: prog.py [-h]
957db96d56Sopenharmony_ci   prog.py: error: unrecognized arguments: foo
967db96d56Sopenharmony_ci
977db96d56Sopenharmony_ciHere is what is happening:
987db96d56Sopenharmony_ci
997db96d56Sopenharmony_ci* Running the script without any options results in nothing displayed to
1007db96d56Sopenharmony_ci  stdout. Not so useful.
1017db96d56Sopenharmony_ci
1027db96d56Sopenharmony_ci* The second one starts to display the usefulness of the :mod:`argparse`
1037db96d56Sopenharmony_ci  module. We have done almost nothing, but already we get a nice help message.
1047db96d56Sopenharmony_ci
1057db96d56Sopenharmony_ci* The ``--help`` option, which can also be shortened to ``-h``, is the only
1067db96d56Sopenharmony_ci  option we get for free (i.e. no need to specify it). Specifying anything
1077db96d56Sopenharmony_ci  else results in an error. But even then, we do get a useful usage message,
1087db96d56Sopenharmony_ci  also for free.
1097db96d56Sopenharmony_ci
1107db96d56Sopenharmony_ci
1117db96d56Sopenharmony_ciIntroducing Positional arguments
1127db96d56Sopenharmony_ci================================
1137db96d56Sopenharmony_ci
1147db96d56Sopenharmony_ciAn example::
1157db96d56Sopenharmony_ci
1167db96d56Sopenharmony_ci   import argparse
1177db96d56Sopenharmony_ci   parser = argparse.ArgumentParser()
1187db96d56Sopenharmony_ci   parser.add_argument("echo")
1197db96d56Sopenharmony_ci   args = parser.parse_args()
1207db96d56Sopenharmony_ci   print(args.echo)
1217db96d56Sopenharmony_ci
1227db96d56Sopenharmony_ciAnd running the code:
1237db96d56Sopenharmony_ci
1247db96d56Sopenharmony_ci.. code-block:: shell-session
1257db96d56Sopenharmony_ci
1267db96d56Sopenharmony_ci   $ python3 prog.py
1277db96d56Sopenharmony_ci   usage: prog.py [-h] echo
1287db96d56Sopenharmony_ci   prog.py: error: the following arguments are required: echo
1297db96d56Sopenharmony_ci   $ python3 prog.py --help
1307db96d56Sopenharmony_ci   usage: prog.py [-h] echo
1317db96d56Sopenharmony_ci
1327db96d56Sopenharmony_ci   positional arguments:
1337db96d56Sopenharmony_ci     echo
1347db96d56Sopenharmony_ci
1357db96d56Sopenharmony_ci   options:
1367db96d56Sopenharmony_ci     -h, --help  show this help message and exit
1377db96d56Sopenharmony_ci   $ python3 prog.py foo
1387db96d56Sopenharmony_ci   foo
1397db96d56Sopenharmony_ci
1407db96d56Sopenharmony_ciHere is what's happening:
1417db96d56Sopenharmony_ci
1427db96d56Sopenharmony_ci* We've added the :meth:`~ArgumentParser.add_argument` method, which is what we use to specify
1437db96d56Sopenharmony_ci  which command-line options the program is willing to accept. In this case,
1447db96d56Sopenharmony_ci  I've named it ``echo`` so that it's in line with its function.
1457db96d56Sopenharmony_ci
1467db96d56Sopenharmony_ci* Calling our program now requires us to specify an option.
1477db96d56Sopenharmony_ci
1487db96d56Sopenharmony_ci* The :meth:`~ArgumentParser.parse_args` method actually returns some data from the
1497db96d56Sopenharmony_ci  options specified, in this case, ``echo``.
1507db96d56Sopenharmony_ci
1517db96d56Sopenharmony_ci* The variable is some form of 'magic' that :mod:`argparse` performs for free
1527db96d56Sopenharmony_ci  (i.e. no need to specify which variable that value is stored in).
1537db96d56Sopenharmony_ci  You will also notice that its name matches the string argument given
1547db96d56Sopenharmony_ci  to the method, ``echo``.
1557db96d56Sopenharmony_ci
1567db96d56Sopenharmony_ciNote however that, although the help display looks nice and all, it currently
1577db96d56Sopenharmony_ciis not as helpful as it can be. For example we see that we got ``echo`` as a
1587db96d56Sopenharmony_cipositional argument, but we don't know what it does, other than by guessing or
1597db96d56Sopenharmony_ciby reading the source code. So, let's make it a bit more useful::
1607db96d56Sopenharmony_ci
1617db96d56Sopenharmony_ci   import argparse
1627db96d56Sopenharmony_ci   parser = argparse.ArgumentParser()
1637db96d56Sopenharmony_ci   parser.add_argument("echo", help="echo the string you use here")
1647db96d56Sopenharmony_ci   args = parser.parse_args()
1657db96d56Sopenharmony_ci   print(args.echo)
1667db96d56Sopenharmony_ci
1677db96d56Sopenharmony_ciAnd we get:
1687db96d56Sopenharmony_ci
1697db96d56Sopenharmony_ci.. code-block:: shell-session
1707db96d56Sopenharmony_ci
1717db96d56Sopenharmony_ci   $ python3 prog.py -h
1727db96d56Sopenharmony_ci   usage: prog.py [-h] echo
1737db96d56Sopenharmony_ci
1747db96d56Sopenharmony_ci   positional arguments:
1757db96d56Sopenharmony_ci     echo        echo the string you use here
1767db96d56Sopenharmony_ci
1777db96d56Sopenharmony_ci   options:
1787db96d56Sopenharmony_ci     -h, --help  show this help message and exit
1797db96d56Sopenharmony_ci
1807db96d56Sopenharmony_ciNow, how about doing something even more useful::
1817db96d56Sopenharmony_ci
1827db96d56Sopenharmony_ci   import argparse
1837db96d56Sopenharmony_ci   parser = argparse.ArgumentParser()
1847db96d56Sopenharmony_ci   parser.add_argument("square", help="display a square of a given number")
1857db96d56Sopenharmony_ci   args = parser.parse_args()
1867db96d56Sopenharmony_ci   print(args.square**2)
1877db96d56Sopenharmony_ci
1887db96d56Sopenharmony_ciFollowing is a result of running the code:
1897db96d56Sopenharmony_ci
1907db96d56Sopenharmony_ci.. code-block:: shell-session
1917db96d56Sopenharmony_ci
1927db96d56Sopenharmony_ci   $ python3 prog.py 4
1937db96d56Sopenharmony_ci   Traceback (most recent call last):
1947db96d56Sopenharmony_ci     File "prog.py", line 5, in <module>
1957db96d56Sopenharmony_ci       print(args.square**2)
1967db96d56Sopenharmony_ci   TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'
1977db96d56Sopenharmony_ci
1987db96d56Sopenharmony_ciThat didn't go so well. That's because :mod:`argparse` treats the options we
1997db96d56Sopenharmony_cigive it as strings, unless we tell it otherwise. So, let's tell
2007db96d56Sopenharmony_ci:mod:`argparse` to treat that input as an integer::
2017db96d56Sopenharmony_ci
2027db96d56Sopenharmony_ci   import argparse
2037db96d56Sopenharmony_ci   parser = argparse.ArgumentParser()
2047db96d56Sopenharmony_ci   parser.add_argument("square", help="display a square of a given number",
2057db96d56Sopenharmony_ci                       type=int)
2067db96d56Sopenharmony_ci   args = parser.parse_args()
2077db96d56Sopenharmony_ci   print(args.square**2)
2087db96d56Sopenharmony_ci
2097db96d56Sopenharmony_ciFollowing is a result of running the code:
2107db96d56Sopenharmony_ci
2117db96d56Sopenharmony_ci.. code-block:: shell-session
2127db96d56Sopenharmony_ci
2137db96d56Sopenharmony_ci   $ python3 prog.py 4
2147db96d56Sopenharmony_ci   16
2157db96d56Sopenharmony_ci   $ python3 prog.py four
2167db96d56Sopenharmony_ci   usage: prog.py [-h] square
2177db96d56Sopenharmony_ci   prog.py: error: argument square: invalid int value: 'four'
2187db96d56Sopenharmony_ci
2197db96d56Sopenharmony_ciThat went well. The program now even helpfully quits on bad illegal input
2207db96d56Sopenharmony_cibefore proceeding.
2217db96d56Sopenharmony_ci
2227db96d56Sopenharmony_ci
2237db96d56Sopenharmony_ciIntroducing Optional arguments
2247db96d56Sopenharmony_ci==============================
2257db96d56Sopenharmony_ci
2267db96d56Sopenharmony_ciSo far we have been playing with positional arguments. Let us
2277db96d56Sopenharmony_cihave a look on how to add optional ones::
2287db96d56Sopenharmony_ci
2297db96d56Sopenharmony_ci   import argparse
2307db96d56Sopenharmony_ci   parser = argparse.ArgumentParser()
2317db96d56Sopenharmony_ci   parser.add_argument("--verbosity", help="increase output verbosity")
2327db96d56Sopenharmony_ci   args = parser.parse_args()
2337db96d56Sopenharmony_ci   if args.verbosity:
2347db96d56Sopenharmony_ci       print("verbosity turned on")
2357db96d56Sopenharmony_ci
2367db96d56Sopenharmony_ciAnd the output:
2377db96d56Sopenharmony_ci
2387db96d56Sopenharmony_ci.. code-block:: shell-session
2397db96d56Sopenharmony_ci
2407db96d56Sopenharmony_ci   $ python3 prog.py --verbosity 1
2417db96d56Sopenharmony_ci   verbosity turned on
2427db96d56Sopenharmony_ci   $ python3 prog.py
2437db96d56Sopenharmony_ci   $ python3 prog.py --help
2447db96d56Sopenharmony_ci   usage: prog.py [-h] [--verbosity VERBOSITY]
2457db96d56Sopenharmony_ci
2467db96d56Sopenharmony_ci   options:
2477db96d56Sopenharmony_ci     -h, --help            show this help message and exit
2487db96d56Sopenharmony_ci     --verbosity VERBOSITY
2497db96d56Sopenharmony_ci                           increase output verbosity
2507db96d56Sopenharmony_ci   $ python3 prog.py --verbosity
2517db96d56Sopenharmony_ci   usage: prog.py [-h] [--verbosity VERBOSITY]
2527db96d56Sopenharmony_ci   prog.py: error: argument --verbosity: expected one argument
2537db96d56Sopenharmony_ci
2547db96d56Sopenharmony_ciHere is what is happening:
2557db96d56Sopenharmony_ci
2567db96d56Sopenharmony_ci* The program is written so as to display something when ``--verbosity`` is
2577db96d56Sopenharmony_ci  specified and display nothing when not.
2587db96d56Sopenharmony_ci
2597db96d56Sopenharmony_ci* To show that the option is actually optional, there is no error when running
2607db96d56Sopenharmony_ci  the program without it. Note that by default, if an optional argument isn't
2617db96d56Sopenharmony_ci  used, the relevant variable, in this case ``args.verbosity``, is
2627db96d56Sopenharmony_ci  given ``None`` as a value, which is the reason it fails the truth
2637db96d56Sopenharmony_ci  test of the :keyword:`if` statement.
2647db96d56Sopenharmony_ci
2657db96d56Sopenharmony_ci* The help message is a bit different.
2667db96d56Sopenharmony_ci
2677db96d56Sopenharmony_ci* When using the ``--verbosity`` option, one must also specify some value,
2687db96d56Sopenharmony_ci  any value.
2697db96d56Sopenharmony_ci
2707db96d56Sopenharmony_ciThe above example accepts arbitrary integer values for ``--verbosity``, but for
2717db96d56Sopenharmony_ciour simple program, only two values are actually useful, ``True`` or ``False``.
2727db96d56Sopenharmony_ciLet's modify the code accordingly::
2737db96d56Sopenharmony_ci
2747db96d56Sopenharmony_ci   import argparse
2757db96d56Sopenharmony_ci   parser = argparse.ArgumentParser()
2767db96d56Sopenharmony_ci   parser.add_argument("--verbose", help="increase output verbosity",
2777db96d56Sopenharmony_ci                       action="store_true")
2787db96d56Sopenharmony_ci   args = parser.parse_args()
2797db96d56Sopenharmony_ci   if args.verbose:
2807db96d56Sopenharmony_ci       print("verbosity turned on")
2817db96d56Sopenharmony_ci
2827db96d56Sopenharmony_ciAnd the output:
2837db96d56Sopenharmony_ci
2847db96d56Sopenharmony_ci.. code-block:: shell-session
2857db96d56Sopenharmony_ci
2867db96d56Sopenharmony_ci   $ python3 prog.py --verbose
2877db96d56Sopenharmony_ci   verbosity turned on
2887db96d56Sopenharmony_ci   $ python3 prog.py --verbose 1
2897db96d56Sopenharmony_ci   usage: prog.py [-h] [--verbose]
2907db96d56Sopenharmony_ci   prog.py: error: unrecognized arguments: 1
2917db96d56Sopenharmony_ci   $ python3 prog.py --help
2927db96d56Sopenharmony_ci   usage: prog.py [-h] [--verbose]
2937db96d56Sopenharmony_ci
2947db96d56Sopenharmony_ci   options:
2957db96d56Sopenharmony_ci     -h, --help  show this help message and exit
2967db96d56Sopenharmony_ci     --verbose   increase output verbosity
2977db96d56Sopenharmony_ci
2987db96d56Sopenharmony_ciHere is what is happening:
2997db96d56Sopenharmony_ci
3007db96d56Sopenharmony_ci* The option is now more of a flag than something that requires a value.
3017db96d56Sopenharmony_ci  We even changed the name of the option to match that idea.
3027db96d56Sopenharmony_ci  Note that we now specify a new keyword, ``action``, and give it the value
3037db96d56Sopenharmony_ci  ``"store_true"``. This means that, if the option is specified,
3047db96d56Sopenharmony_ci  assign the value ``True`` to ``args.verbose``.
3057db96d56Sopenharmony_ci  Not specifying it implies ``False``.
3067db96d56Sopenharmony_ci
3077db96d56Sopenharmony_ci* It complains when you specify a value, in true spirit of what flags
3087db96d56Sopenharmony_ci  actually are.
3097db96d56Sopenharmony_ci
3107db96d56Sopenharmony_ci* Notice the different help text.
3117db96d56Sopenharmony_ci
3127db96d56Sopenharmony_ci
3137db96d56Sopenharmony_ciShort options
3147db96d56Sopenharmony_ci-------------
3157db96d56Sopenharmony_ci
3167db96d56Sopenharmony_ciIf you are familiar with command line usage,
3177db96d56Sopenharmony_ciyou will notice that I haven't yet touched on the topic of short
3187db96d56Sopenharmony_civersions of the options. It's quite simple::
3197db96d56Sopenharmony_ci
3207db96d56Sopenharmony_ci   import argparse
3217db96d56Sopenharmony_ci   parser = argparse.ArgumentParser()
3227db96d56Sopenharmony_ci   parser.add_argument("-v", "--verbose", help="increase output verbosity",
3237db96d56Sopenharmony_ci                       action="store_true")
3247db96d56Sopenharmony_ci   args = parser.parse_args()
3257db96d56Sopenharmony_ci   if args.verbose:
3267db96d56Sopenharmony_ci       print("verbosity turned on")
3277db96d56Sopenharmony_ci
3287db96d56Sopenharmony_ciAnd here goes:
3297db96d56Sopenharmony_ci
3307db96d56Sopenharmony_ci.. code-block:: shell-session
3317db96d56Sopenharmony_ci
3327db96d56Sopenharmony_ci   $ python3 prog.py -v
3337db96d56Sopenharmony_ci   verbosity turned on
3347db96d56Sopenharmony_ci   $ python3 prog.py --help
3357db96d56Sopenharmony_ci   usage: prog.py [-h] [-v]
3367db96d56Sopenharmony_ci
3377db96d56Sopenharmony_ci   options:
3387db96d56Sopenharmony_ci     -h, --help     show this help message and exit
3397db96d56Sopenharmony_ci     -v, --verbose  increase output verbosity
3407db96d56Sopenharmony_ci
3417db96d56Sopenharmony_ciNote that the new ability is also reflected in the help text.
3427db96d56Sopenharmony_ci
3437db96d56Sopenharmony_ci
3447db96d56Sopenharmony_ciCombining Positional and Optional arguments
3457db96d56Sopenharmony_ci===========================================
3467db96d56Sopenharmony_ci
3477db96d56Sopenharmony_ciOur program keeps growing in complexity::
3487db96d56Sopenharmony_ci
3497db96d56Sopenharmony_ci   import argparse
3507db96d56Sopenharmony_ci   parser = argparse.ArgumentParser()
3517db96d56Sopenharmony_ci   parser.add_argument("square", type=int,
3527db96d56Sopenharmony_ci                       help="display a square of a given number")
3537db96d56Sopenharmony_ci   parser.add_argument("-v", "--verbose", action="store_true",
3547db96d56Sopenharmony_ci                       help="increase output verbosity")
3557db96d56Sopenharmony_ci   args = parser.parse_args()
3567db96d56Sopenharmony_ci   answer = args.square**2
3577db96d56Sopenharmony_ci   if args.verbose:
3587db96d56Sopenharmony_ci       print(f"the square of {args.square} equals {answer}")
3597db96d56Sopenharmony_ci   else:
3607db96d56Sopenharmony_ci       print(answer)
3617db96d56Sopenharmony_ci
3627db96d56Sopenharmony_ciAnd now the output:
3637db96d56Sopenharmony_ci
3647db96d56Sopenharmony_ci.. code-block:: shell-session
3657db96d56Sopenharmony_ci
3667db96d56Sopenharmony_ci   $ python3 prog.py
3677db96d56Sopenharmony_ci   usage: prog.py [-h] [-v] square
3687db96d56Sopenharmony_ci   prog.py: error: the following arguments are required: square
3697db96d56Sopenharmony_ci   $ python3 prog.py 4
3707db96d56Sopenharmony_ci   16
3717db96d56Sopenharmony_ci   $ python3 prog.py 4 --verbose
3727db96d56Sopenharmony_ci   the square of 4 equals 16
3737db96d56Sopenharmony_ci   $ python3 prog.py --verbose 4
3747db96d56Sopenharmony_ci   the square of 4 equals 16
3757db96d56Sopenharmony_ci
3767db96d56Sopenharmony_ci* We've brought back a positional argument, hence the complaint.
3777db96d56Sopenharmony_ci
3787db96d56Sopenharmony_ci* Note that the order does not matter.
3797db96d56Sopenharmony_ci
3807db96d56Sopenharmony_ciHow about we give this program of ours back the ability to have
3817db96d56Sopenharmony_cimultiple verbosity values, and actually get to use them::
3827db96d56Sopenharmony_ci
3837db96d56Sopenharmony_ci   import argparse
3847db96d56Sopenharmony_ci   parser = argparse.ArgumentParser()
3857db96d56Sopenharmony_ci   parser.add_argument("square", type=int,
3867db96d56Sopenharmony_ci                       help="display a square of a given number")
3877db96d56Sopenharmony_ci   parser.add_argument("-v", "--verbosity", type=int,
3887db96d56Sopenharmony_ci                       help="increase output verbosity")
3897db96d56Sopenharmony_ci   args = parser.parse_args()
3907db96d56Sopenharmony_ci   answer = args.square**2
3917db96d56Sopenharmony_ci   if args.verbosity == 2:
3927db96d56Sopenharmony_ci       print(f"the square of {args.square} equals {answer}")
3937db96d56Sopenharmony_ci   elif args.verbosity == 1:
3947db96d56Sopenharmony_ci       print(f"{args.square}^2 == {answer}")
3957db96d56Sopenharmony_ci   else:
3967db96d56Sopenharmony_ci       print(answer)
3977db96d56Sopenharmony_ci
3987db96d56Sopenharmony_ciAnd the output:
3997db96d56Sopenharmony_ci
4007db96d56Sopenharmony_ci.. code-block:: shell-session
4017db96d56Sopenharmony_ci
4027db96d56Sopenharmony_ci   $ python3 prog.py 4
4037db96d56Sopenharmony_ci   16
4047db96d56Sopenharmony_ci   $ python3 prog.py 4 -v
4057db96d56Sopenharmony_ci   usage: prog.py [-h] [-v VERBOSITY] square
4067db96d56Sopenharmony_ci   prog.py: error: argument -v/--verbosity: expected one argument
4077db96d56Sopenharmony_ci   $ python3 prog.py 4 -v 1
4087db96d56Sopenharmony_ci   4^2 == 16
4097db96d56Sopenharmony_ci   $ python3 prog.py 4 -v 2
4107db96d56Sopenharmony_ci   the square of 4 equals 16
4117db96d56Sopenharmony_ci   $ python3 prog.py 4 -v 3
4127db96d56Sopenharmony_ci   16
4137db96d56Sopenharmony_ci
4147db96d56Sopenharmony_ciThese all look good except the last one, which exposes a bug in our program.
4157db96d56Sopenharmony_ciLet's fix it by restricting the values the ``--verbosity`` option can accept::
4167db96d56Sopenharmony_ci
4177db96d56Sopenharmony_ci   import argparse
4187db96d56Sopenharmony_ci   parser = argparse.ArgumentParser()
4197db96d56Sopenharmony_ci   parser.add_argument("square", type=int,
4207db96d56Sopenharmony_ci                       help="display a square of a given number")
4217db96d56Sopenharmony_ci   parser.add_argument("-v", "--verbosity", type=int, choices=[0, 1, 2],
4227db96d56Sopenharmony_ci                       help="increase output verbosity")
4237db96d56Sopenharmony_ci   args = parser.parse_args()
4247db96d56Sopenharmony_ci   answer = args.square**2
4257db96d56Sopenharmony_ci   if args.verbosity == 2:
4267db96d56Sopenharmony_ci       print(f"the square of {args.square} equals {answer}")
4277db96d56Sopenharmony_ci   elif args.verbosity == 1:
4287db96d56Sopenharmony_ci       print(f"{args.square}^2 == {answer}")
4297db96d56Sopenharmony_ci   else:
4307db96d56Sopenharmony_ci       print(answer)
4317db96d56Sopenharmony_ci
4327db96d56Sopenharmony_ciAnd the output:
4337db96d56Sopenharmony_ci
4347db96d56Sopenharmony_ci.. code-block:: shell-session
4357db96d56Sopenharmony_ci
4367db96d56Sopenharmony_ci   $ python3 prog.py 4 -v 3
4377db96d56Sopenharmony_ci   usage: prog.py [-h] [-v {0,1,2}] square
4387db96d56Sopenharmony_ci   prog.py: error: argument -v/--verbosity: invalid choice: 3 (choose from 0, 1, 2)
4397db96d56Sopenharmony_ci   $ python3 prog.py 4 -h
4407db96d56Sopenharmony_ci   usage: prog.py [-h] [-v {0,1,2}] square
4417db96d56Sopenharmony_ci
4427db96d56Sopenharmony_ci   positional arguments:
4437db96d56Sopenharmony_ci     square                display a square of a given number
4447db96d56Sopenharmony_ci
4457db96d56Sopenharmony_ci   options:
4467db96d56Sopenharmony_ci     -h, --help            show this help message and exit
4477db96d56Sopenharmony_ci     -v {0,1,2}, --verbosity {0,1,2}
4487db96d56Sopenharmony_ci                           increase output verbosity
4497db96d56Sopenharmony_ci
4507db96d56Sopenharmony_ciNote that the change also reflects both in the error message as well as the
4517db96d56Sopenharmony_cihelp string.
4527db96d56Sopenharmony_ci
4537db96d56Sopenharmony_ciNow, let's use a different approach of playing with verbosity, which is pretty
4547db96d56Sopenharmony_cicommon. It also matches the way the CPython executable handles its own
4557db96d56Sopenharmony_civerbosity argument (check the output of ``python --help``)::
4567db96d56Sopenharmony_ci
4577db96d56Sopenharmony_ci   import argparse
4587db96d56Sopenharmony_ci   parser = argparse.ArgumentParser()
4597db96d56Sopenharmony_ci   parser.add_argument("square", type=int,
4607db96d56Sopenharmony_ci                       help="display the square of a given number")
4617db96d56Sopenharmony_ci   parser.add_argument("-v", "--verbosity", action="count",
4627db96d56Sopenharmony_ci                       help="increase output verbosity")
4637db96d56Sopenharmony_ci   args = parser.parse_args()
4647db96d56Sopenharmony_ci   answer = args.square**2
4657db96d56Sopenharmony_ci   if args.verbosity == 2:
4667db96d56Sopenharmony_ci       print(f"the square of {args.square} equals {answer}")
4677db96d56Sopenharmony_ci   elif args.verbosity == 1:
4687db96d56Sopenharmony_ci       print(f"{args.square}^2 == {answer}")
4697db96d56Sopenharmony_ci   else:
4707db96d56Sopenharmony_ci       print(answer)
4717db96d56Sopenharmony_ci
4727db96d56Sopenharmony_ciWe have introduced another action, "count",
4737db96d56Sopenharmony_cito count the number of occurrences of specific options.
4747db96d56Sopenharmony_ci
4757db96d56Sopenharmony_ci
4767db96d56Sopenharmony_ci.. code-block:: shell-session
4777db96d56Sopenharmony_ci
4787db96d56Sopenharmony_ci   $ python3 prog.py 4
4797db96d56Sopenharmony_ci   16
4807db96d56Sopenharmony_ci   $ python3 prog.py 4 -v
4817db96d56Sopenharmony_ci   4^2 == 16
4827db96d56Sopenharmony_ci   $ python3 prog.py 4 -vv
4837db96d56Sopenharmony_ci   the square of 4 equals 16
4847db96d56Sopenharmony_ci   $ python3 prog.py 4 --verbosity --verbosity
4857db96d56Sopenharmony_ci   the square of 4 equals 16
4867db96d56Sopenharmony_ci   $ python3 prog.py 4 -v 1
4877db96d56Sopenharmony_ci   usage: prog.py [-h] [-v] square
4887db96d56Sopenharmony_ci   prog.py: error: unrecognized arguments: 1
4897db96d56Sopenharmony_ci   $ python3 prog.py 4 -h
4907db96d56Sopenharmony_ci   usage: prog.py [-h] [-v] square
4917db96d56Sopenharmony_ci
4927db96d56Sopenharmony_ci   positional arguments:
4937db96d56Sopenharmony_ci     square           display a square of a given number
4947db96d56Sopenharmony_ci
4957db96d56Sopenharmony_ci   options:
4967db96d56Sopenharmony_ci     -h, --help       show this help message and exit
4977db96d56Sopenharmony_ci     -v, --verbosity  increase output verbosity
4987db96d56Sopenharmony_ci   $ python3 prog.py 4 -vvv
4997db96d56Sopenharmony_ci   16
5007db96d56Sopenharmony_ci
5017db96d56Sopenharmony_ci* Yes, it's now more of a flag (similar to ``action="store_true"``) in the
5027db96d56Sopenharmony_ci  previous version of our script. That should explain the complaint.
5037db96d56Sopenharmony_ci
5047db96d56Sopenharmony_ci* It also behaves similar to "store_true" action.
5057db96d56Sopenharmony_ci
5067db96d56Sopenharmony_ci* Now here's a demonstration of what the "count" action gives. You've probably
5077db96d56Sopenharmony_ci  seen this sort of usage before.
5087db96d56Sopenharmony_ci
5097db96d56Sopenharmony_ci* And if you don't specify the ``-v`` flag, that flag is considered to have
5107db96d56Sopenharmony_ci  ``None`` value.
5117db96d56Sopenharmony_ci
5127db96d56Sopenharmony_ci* As should be expected, specifying the long form of the flag, we should get
5137db96d56Sopenharmony_ci  the same output.
5147db96d56Sopenharmony_ci
5157db96d56Sopenharmony_ci* Sadly, our help output isn't very informative on the new ability our script
5167db96d56Sopenharmony_ci  has acquired, but that can always be fixed by improving the documentation for
5177db96d56Sopenharmony_ci  our script (e.g. via the ``help`` keyword argument).
5187db96d56Sopenharmony_ci
5197db96d56Sopenharmony_ci* That last output exposes a bug in our program.
5207db96d56Sopenharmony_ci
5217db96d56Sopenharmony_ci
5227db96d56Sopenharmony_ciLet's fix::
5237db96d56Sopenharmony_ci
5247db96d56Sopenharmony_ci   import argparse
5257db96d56Sopenharmony_ci   parser = argparse.ArgumentParser()
5267db96d56Sopenharmony_ci   parser.add_argument("square", type=int,
5277db96d56Sopenharmony_ci                       help="display a square of a given number")
5287db96d56Sopenharmony_ci   parser.add_argument("-v", "--verbosity", action="count",
5297db96d56Sopenharmony_ci                       help="increase output verbosity")
5307db96d56Sopenharmony_ci   args = parser.parse_args()
5317db96d56Sopenharmony_ci   answer = args.square**2
5327db96d56Sopenharmony_ci
5337db96d56Sopenharmony_ci   # bugfix: replace == with >=
5347db96d56Sopenharmony_ci   if args.verbosity >= 2:
5357db96d56Sopenharmony_ci       print(f"the square of {args.square} equals {answer}")
5367db96d56Sopenharmony_ci   elif args.verbosity >= 1:
5377db96d56Sopenharmony_ci       print(f"{args.square}^2 == {answer}")
5387db96d56Sopenharmony_ci   else:
5397db96d56Sopenharmony_ci       print(answer)
5407db96d56Sopenharmony_ci
5417db96d56Sopenharmony_ciAnd this is what it gives:
5427db96d56Sopenharmony_ci
5437db96d56Sopenharmony_ci.. code-block:: shell-session
5447db96d56Sopenharmony_ci
5457db96d56Sopenharmony_ci   $ python3 prog.py 4 -vvv
5467db96d56Sopenharmony_ci   the square of 4 equals 16
5477db96d56Sopenharmony_ci   $ python3 prog.py 4 -vvvv
5487db96d56Sopenharmony_ci   the square of 4 equals 16
5497db96d56Sopenharmony_ci   $ python3 prog.py 4
5507db96d56Sopenharmony_ci   Traceback (most recent call last):
5517db96d56Sopenharmony_ci     File "prog.py", line 11, in <module>
5527db96d56Sopenharmony_ci       if args.verbosity >= 2:
5537db96d56Sopenharmony_ci   TypeError: '>=' not supported between instances of 'NoneType' and 'int'
5547db96d56Sopenharmony_ci
5557db96d56Sopenharmony_ci
5567db96d56Sopenharmony_ci* First output went well, and fixes the bug we had before.
5577db96d56Sopenharmony_ci  That is, we want any value >= 2 to be as verbose as possible.
5587db96d56Sopenharmony_ci
5597db96d56Sopenharmony_ci* Third output not so good.
5607db96d56Sopenharmony_ci
5617db96d56Sopenharmony_ciLet's fix that bug::
5627db96d56Sopenharmony_ci
5637db96d56Sopenharmony_ci   import argparse
5647db96d56Sopenharmony_ci   parser = argparse.ArgumentParser()
5657db96d56Sopenharmony_ci   parser.add_argument("square", type=int,
5667db96d56Sopenharmony_ci                       help="display a square of a given number")
5677db96d56Sopenharmony_ci   parser.add_argument("-v", "--verbosity", action="count", default=0,
5687db96d56Sopenharmony_ci                       help="increase output verbosity")
5697db96d56Sopenharmony_ci   args = parser.parse_args()
5707db96d56Sopenharmony_ci   answer = args.square**2
5717db96d56Sopenharmony_ci   if args.verbosity >= 2:
5727db96d56Sopenharmony_ci       print(f"the square of {args.square} equals {answer}")
5737db96d56Sopenharmony_ci   elif args.verbosity >= 1:
5747db96d56Sopenharmony_ci       print(f"{args.square}^2 == {answer}")
5757db96d56Sopenharmony_ci   else:
5767db96d56Sopenharmony_ci       print(answer)
5777db96d56Sopenharmony_ci
5787db96d56Sopenharmony_ciWe've just introduced yet another keyword, ``default``.
5797db96d56Sopenharmony_ciWe've set it to ``0`` in order to make it comparable to the other int values.
5807db96d56Sopenharmony_ciRemember that by default,
5817db96d56Sopenharmony_ciif an optional argument isn't specified,
5827db96d56Sopenharmony_ciit gets the ``None`` value, and that cannot be compared to an int value
5837db96d56Sopenharmony_ci(hence the :exc:`TypeError` exception).
5847db96d56Sopenharmony_ci
5857db96d56Sopenharmony_ciAnd:
5867db96d56Sopenharmony_ci
5877db96d56Sopenharmony_ci.. code-block:: shell-session
5887db96d56Sopenharmony_ci
5897db96d56Sopenharmony_ci   $ python3 prog.py 4
5907db96d56Sopenharmony_ci   16
5917db96d56Sopenharmony_ci
5927db96d56Sopenharmony_ciYou can go quite far just with what we've learned so far,
5937db96d56Sopenharmony_ciand we have only scratched the surface.
5947db96d56Sopenharmony_ciThe :mod:`argparse` module is very powerful,
5957db96d56Sopenharmony_ciand we'll explore a bit more of it before we end this tutorial.
5967db96d56Sopenharmony_ci
5977db96d56Sopenharmony_ci
5987db96d56Sopenharmony_ciGetting a little more advanced
5997db96d56Sopenharmony_ci==============================
6007db96d56Sopenharmony_ci
6017db96d56Sopenharmony_ciWhat if we wanted to expand our tiny program to perform other powers,
6027db96d56Sopenharmony_cinot just squares::
6037db96d56Sopenharmony_ci
6047db96d56Sopenharmony_ci   import argparse
6057db96d56Sopenharmony_ci   parser = argparse.ArgumentParser()
6067db96d56Sopenharmony_ci   parser.add_argument("x", type=int, help="the base")
6077db96d56Sopenharmony_ci   parser.add_argument("y", type=int, help="the exponent")
6087db96d56Sopenharmony_ci   parser.add_argument("-v", "--verbosity", action="count", default=0)
6097db96d56Sopenharmony_ci   args = parser.parse_args()
6107db96d56Sopenharmony_ci   answer = args.x**args.y
6117db96d56Sopenharmony_ci   if args.verbosity >= 2:
6127db96d56Sopenharmony_ci       print(f"{args.x} to the power {args.y} equals {answer}")
6137db96d56Sopenharmony_ci   elif args.verbosity >= 1:
6147db96d56Sopenharmony_ci       print(f"{args.x}^{args.y} == {answer}")
6157db96d56Sopenharmony_ci   else:
6167db96d56Sopenharmony_ci       print(answer)
6177db96d56Sopenharmony_ci
6187db96d56Sopenharmony_ciOutput:
6197db96d56Sopenharmony_ci
6207db96d56Sopenharmony_ci.. code-block:: shell-session
6217db96d56Sopenharmony_ci
6227db96d56Sopenharmony_ci   $ python3 prog.py
6237db96d56Sopenharmony_ci   usage: prog.py [-h] [-v] x y
6247db96d56Sopenharmony_ci   prog.py: error: the following arguments are required: x, y
6257db96d56Sopenharmony_ci   $ python3 prog.py -h
6267db96d56Sopenharmony_ci   usage: prog.py [-h] [-v] x y
6277db96d56Sopenharmony_ci
6287db96d56Sopenharmony_ci   positional arguments:
6297db96d56Sopenharmony_ci     x                the base
6307db96d56Sopenharmony_ci     y                the exponent
6317db96d56Sopenharmony_ci
6327db96d56Sopenharmony_ci   options:
6337db96d56Sopenharmony_ci     -h, --help       show this help message and exit
6347db96d56Sopenharmony_ci     -v, --verbosity
6357db96d56Sopenharmony_ci   $ python3 prog.py 4 2 -v
6367db96d56Sopenharmony_ci   4^2 == 16
6377db96d56Sopenharmony_ci
6387db96d56Sopenharmony_ci
6397db96d56Sopenharmony_ciNotice that so far we've been using verbosity level to *change* the text
6407db96d56Sopenharmony_cithat gets displayed. The following example instead uses verbosity level
6417db96d56Sopenharmony_cito display *more* text instead::
6427db96d56Sopenharmony_ci
6437db96d56Sopenharmony_ci   import argparse
6447db96d56Sopenharmony_ci   parser = argparse.ArgumentParser()
6457db96d56Sopenharmony_ci   parser.add_argument("x", type=int, help="the base")
6467db96d56Sopenharmony_ci   parser.add_argument("y", type=int, help="the exponent")
6477db96d56Sopenharmony_ci   parser.add_argument("-v", "--verbosity", action="count", default=0)
6487db96d56Sopenharmony_ci   args = parser.parse_args()
6497db96d56Sopenharmony_ci   answer = args.x**args.y
6507db96d56Sopenharmony_ci   if args.verbosity >= 2:
6517db96d56Sopenharmony_ci       print(f"Running '{__file__}'")
6527db96d56Sopenharmony_ci   if args.verbosity >= 1:
6537db96d56Sopenharmony_ci       print(f"{args.x}^{args.y} == ", end="")
6547db96d56Sopenharmony_ci   print(answer)
6557db96d56Sopenharmony_ci
6567db96d56Sopenharmony_ciOutput:
6577db96d56Sopenharmony_ci
6587db96d56Sopenharmony_ci.. code-block:: shell-session
6597db96d56Sopenharmony_ci
6607db96d56Sopenharmony_ci   $ python3 prog.py 4 2
6617db96d56Sopenharmony_ci   16
6627db96d56Sopenharmony_ci   $ python3 prog.py 4 2 -v
6637db96d56Sopenharmony_ci   4^2 == 16
6647db96d56Sopenharmony_ci   $ python3 prog.py 4 2 -vv
6657db96d56Sopenharmony_ci   Running 'prog.py'
6667db96d56Sopenharmony_ci   4^2 == 16
6677db96d56Sopenharmony_ci
6687db96d56Sopenharmony_ci
6697db96d56Sopenharmony_ciConflicting options
6707db96d56Sopenharmony_ci-------------------
6717db96d56Sopenharmony_ci
6727db96d56Sopenharmony_ciSo far, we have been working with two methods of an
6737db96d56Sopenharmony_ci:class:`argparse.ArgumentParser` instance. Let's introduce a third one,
6747db96d56Sopenharmony_ci:meth:`~ArgumentParser.add_mutually_exclusive_group`. It allows for us to specify options that
6757db96d56Sopenharmony_ciconflict with each other. Let's also change the rest of the program so that
6767db96d56Sopenharmony_cithe new functionality makes more sense:
6777db96d56Sopenharmony_ciwe'll introduce the ``--quiet`` option,
6787db96d56Sopenharmony_ciwhich will be the opposite of the ``--verbose`` one::
6797db96d56Sopenharmony_ci
6807db96d56Sopenharmony_ci   import argparse
6817db96d56Sopenharmony_ci
6827db96d56Sopenharmony_ci   parser = argparse.ArgumentParser()
6837db96d56Sopenharmony_ci   group = parser.add_mutually_exclusive_group()
6847db96d56Sopenharmony_ci   group.add_argument("-v", "--verbose", action="store_true")
6857db96d56Sopenharmony_ci   group.add_argument("-q", "--quiet", action="store_true")
6867db96d56Sopenharmony_ci   parser.add_argument("x", type=int, help="the base")
6877db96d56Sopenharmony_ci   parser.add_argument("y", type=int, help="the exponent")
6887db96d56Sopenharmony_ci   args = parser.parse_args()
6897db96d56Sopenharmony_ci   answer = args.x**args.y
6907db96d56Sopenharmony_ci
6917db96d56Sopenharmony_ci   if args.quiet:
6927db96d56Sopenharmony_ci       print(answer)
6937db96d56Sopenharmony_ci   elif args.verbose:
6947db96d56Sopenharmony_ci       print(f"{args.x} to the power {args.y} equals {answer}")
6957db96d56Sopenharmony_ci   else:
6967db96d56Sopenharmony_ci       print(f"{args.x}^{args.y} == {answer}")
6977db96d56Sopenharmony_ci
6987db96d56Sopenharmony_ciOur program is now simpler, and we've lost some functionality for the sake of
6997db96d56Sopenharmony_cidemonstration. Anyways, here's the output:
7007db96d56Sopenharmony_ci
7017db96d56Sopenharmony_ci.. code-block:: shell-session
7027db96d56Sopenharmony_ci
7037db96d56Sopenharmony_ci   $ python3 prog.py 4 2
7047db96d56Sopenharmony_ci   4^2 == 16
7057db96d56Sopenharmony_ci   $ python3 prog.py 4 2 -q
7067db96d56Sopenharmony_ci   16
7077db96d56Sopenharmony_ci   $ python3 prog.py 4 2 -v
7087db96d56Sopenharmony_ci   4 to the power 2 equals 16
7097db96d56Sopenharmony_ci   $ python3 prog.py 4 2 -vq
7107db96d56Sopenharmony_ci   usage: prog.py [-h] [-v | -q] x y
7117db96d56Sopenharmony_ci   prog.py: error: argument -q/--quiet: not allowed with argument -v/--verbose
7127db96d56Sopenharmony_ci   $ python3 prog.py 4 2 -v --quiet
7137db96d56Sopenharmony_ci   usage: prog.py [-h] [-v | -q] x y
7147db96d56Sopenharmony_ci   prog.py: error: argument -q/--quiet: not allowed with argument -v/--verbose
7157db96d56Sopenharmony_ci
7167db96d56Sopenharmony_ciThat should be easy to follow. I've added that last output so you can see the
7177db96d56Sopenharmony_cisort of flexibility you get, i.e. mixing long form options with short form
7187db96d56Sopenharmony_ciones.
7197db96d56Sopenharmony_ci
7207db96d56Sopenharmony_ciBefore we conclude, you probably want to tell your users the main purpose of
7217db96d56Sopenharmony_ciyour program, just in case they don't know::
7227db96d56Sopenharmony_ci
7237db96d56Sopenharmony_ci   import argparse
7247db96d56Sopenharmony_ci
7257db96d56Sopenharmony_ci   parser = argparse.ArgumentParser(description="calculate X to the power of Y")
7267db96d56Sopenharmony_ci   group = parser.add_mutually_exclusive_group()
7277db96d56Sopenharmony_ci   group.add_argument("-v", "--verbose", action="store_true")
7287db96d56Sopenharmony_ci   group.add_argument("-q", "--quiet", action="store_true")
7297db96d56Sopenharmony_ci   parser.add_argument("x", type=int, help="the base")
7307db96d56Sopenharmony_ci   parser.add_argument("y", type=int, help="the exponent")
7317db96d56Sopenharmony_ci   args = parser.parse_args()
7327db96d56Sopenharmony_ci   answer = args.x**args.y
7337db96d56Sopenharmony_ci
7347db96d56Sopenharmony_ci   if args.quiet:
7357db96d56Sopenharmony_ci       print(answer)
7367db96d56Sopenharmony_ci   elif args.verbose:
7377db96d56Sopenharmony_ci       print(f"{args.x} to the power {args.y} equals {answer}")
7387db96d56Sopenharmony_ci   else:
7397db96d56Sopenharmony_ci       print(f"{args.x}^{args.y} == {answer}")
7407db96d56Sopenharmony_ci
7417db96d56Sopenharmony_ciNote that slight difference in the usage text. Note the ``[-v | -q]``,
7427db96d56Sopenharmony_ciwhich tells us that we can either use ``-v`` or ``-q``,
7437db96d56Sopenharmony_cibut not both at the same time:
7447db96d56Sopenharmony_ci
7457db96d56Sopenharmony_ci.. code-block:: shell-session
7467db96d56Sopenharmony_ci
7477db96d56Sopenharmony_ci   $ python3 prog.py --help
7487db96d56Sopenharmony_ci   usage: prog.py [-h] [-v | -q] x y
7497db96d56Sopenharmony_ci
7507db96d56Sopenharmony_ci   calculate X to the power of Y
7517db96d56Sopenharmony_ci
7527db96d56Sopenharmony_ci   positional arguments:
7537db96d56Sopenharmony_ci     x              the base
7547db96d56Sopenharmony_ci     y              the exponent
7557db96d56Sopenharmony_ci
7567db96d56Sopenharmony_ci   options:
7577db96d56Sopenharmony_ci     -h, --help     show this help message and exit
7587db96d56Sopenharmony_ci     -v, --verbose
7597db96d56Sopenharmony_ci     -q, --quiet
7607db96d56Sopenharmony_ci
7617db96d56Sopenharmony_ci
7627db96d56Sopenharmony_ciConclusion
7637db96d56Sopenharmony_ci==========
7647db96d56Sopenharmony_ci
7657db96d56Sopenharmony_ciThe :mod:`argparse` module offers a lot more than shown here.
7667db96d56Sopenharmony_ciIts docs are quite detailed and thorough, and full of examples.
7677db96d56Sopenharmony_ciHaving gone through this tutorial, you should easily digest them
7687db96d56Sopenharmony_ciwithout feeling overwhelmed.
769