Home | History | Annotate | Download | only in howto
      1 *****************
      2 Argparse Tutorial
      3 *****************
      4 
      5 :author: Tshepang Lekhonkhobe
      6 
      7 .. _argparse-tutorial:
      8 
      9 This tutorial is intended to be a gentle introduction to :mod:`argparse`, the
     10 recommended command-line parsing module in the Python standard library.
     11 This was written for argparse in Python 3. A few details are different in 2.x,
     12 especially some exception messages, which were improved in 3.x.
     13 
     14 .. note::
     15 
     16    There are two other modules that fulfill the same task, namely
     17    :mod:`getopt` (an equivalent for :c:func:`getopt` from the C
     18    language) and the deprecated :mod:`optparse`.
     19    Note also that :mod:`argparse` is based on :mod:`optparse`,
     20    and therefore very similar in terms of usage.
     21 
     22 
     23 Concepts
     24 ========
     25 
     26 Let's show the sort of functionality that we are going to explore in this
     27 introductory tutorial by making use of the :command:`ls` command:
     28 
     29 .. code-block:: sh
     30 
     31    $ ls
     32    cpython  devguide  prog.py  pypy  rm-unused-function.patch
     33    $ ls pypy
     34    ctypes_configure  demo  dotviewer  include  lib_pypy  lib-python ...
     35    $ ls -l
     36    total 20
     37    drwxr-xr-x 19 wena wena 4096 Feb 18 18:51 cpython
     38    drwxr-xr-x  4 wena wena 4096 Feb  8 12:04 devguide
     39    -rwxr-xr-x  1 wena wena  535 Feb 19 00:05 prog.py
     40    drwxr-xr-x 14 wena wena 4096 Feb  7 00:59 pypy
     41    -rw-r--r--  1 wena wena  741 Feb 18 01:01 rm-unused-function.patch
     42    $ ls --help
     43    Usage: ls [OPTION]... [FILE]...
     44    List information about the FILEs (the current directory by default).
     45    Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.
     46    ...
     47 
     48 A few concepts we can learn from the four commands:
     49 
     50 * The :command:`ls` command is useful when run without any options at all. It defaults
     51   to displaying the contents of the current directory.
     52 
     53 * If we want beyond what it provides by default, we tell it a bit more. In
     54   this case, we want it to display a different directory, ``pypy``.
     55   What we did is specify what is known as a positional argument. It's named so
     56   because the program should know what to do with the value, solely based on
     57   where it appears on the command line. This concept is more relevant
     58   to a command like :command:`cp`, whose most basic usage is ``cp SRC DEST``.
     59   The first position is *what you want copied,* and the second
     60   position is *where you want it copied to*.
     61 
     62 * Now, say we want to change behaviour of the program. In our example,
     63   we display more info for each file instead of just showing the file names.
     64   The ``-l`` in that case is known as an optional argument.
     65 
     66 * That's a snippet of the help text. It's very useful in that you can
     67   come across a program you have never used before, and can figure out
     68   how it works simply by reading its help text.
     69 
     70 
     71 The basics
     72 ==========
     73 
     74 Let us start with a very simple example which does (almost) nothing::
     75 
     76    import argparse
     77    parser = argparse.ArgumentParser()
     78    parser.parse_args()
     79 
     80 Following is a result of running the code:
     81 
     82 .. code-block:: sh
     83 
     84    $ python prog.py
     85    $ python prog.py --help
     86    usage: prog.py [-h]
     87 
     88    optional arguments:
     89      -h, --help  show this help message and exit
     90    $ python prog.py --verbose
     91    usage: prog.py [-h]
     92    prog.py: error: unrecognized arguments: --verbose
     93    $ python prog.py foo
     94    usage: prog.py [-h]
     95    prog.py: error: unrecognized arguments: foo
     96 
     97 Here is what is happening:
     98 
     99 * Running the script without any options results in nothing displayed to
    100   stdout. Not so useful.
    101 
    102 * The second one starts to display the usefulness of the :mod:`argparse`
    103   module. We have done almost nothing, but already we get a nice help message.
    104 
    105 * The ``--help`` option, which can also be shortened to ``-h``, is the only
    106   option we get for free (i.e. no need to specify it). Specifying anything
    107   else results in an error. But even then, we do get a useful usage message,
    108   also for free.
    109 
    110 
    111 Introducing Positional arguments
    112 ================================
    113 
    114 An example::
    115 
    116    import argparse
    117    parser = argparse.ArgumentParser()
    118    parser.add_argument("echo")
    119    args = parser.parse_args()
    120    print args.echo
    121 
    122 And running the code:
    123 
    124 .. code-block:: sh
    125 
    126    $ python prog.py
    127    usage: prog.py [-h] echo
    128    prog.py: error: the following arguments are required: echo
    129    $ python prog.py --help
    130    usage: prog.py [-h] echo
    131 
    132    positional arguments:
    133      echo
    134 
    135    optional arguments:
    136      -h, --help  show this help message and exit
    137    $ python prog.py foo
    138    foo
    139 
    140 Here is what's happening:
    141 
    142 * We've added the :meth:`add_argument` method, which is what we use to specify
    143   which command-line options the program is willing to accept. In this case,
    144   I've named it ``echo`` so that it's in line with its function.
    145 
    146 * Calling our program now requires us to specify an option.
    147 
    148 * The :meth:`parse_args` method actually returns some data from the
    149   options specified, in this case, ``echo``.
    150 
    151 * The variable is some form of 'magic' that :mod:`argparse` performs for free
    152   (i.e. no need to specify which variable that value is stored in).
    153   You will also notice that its name matches the string argument given
    154   to the method, ``echo``.
    155 
    156 Note however that, although the help display looks nice and all, it currently
    157 is not as helpful as it can be. For example we see that we got ``echo`` as a
    158 positional argument, but we don't know what it does, other than by guessing or
    159 by reading the source code. So, let's make it a bit more useful::
    160 
    161    import argparse
    162    parser = argparse.ArgumentParser()
    163    parser.add_argument("echo", help="echo the string you use here")
    164    args = parser.parse_args()
    165    print args.echo
    166 
    167 And we get:
    168 
    169 .. code-block:: sh
    170 
    171    $ python prog.py -h
    172    usage: prog.py [-h] echo
    173 
    174    positional arguments:
    175      echo        echo the string you use here
    176 
    177    optional arguments:
    178      -h, --help  show this help message and exit
    179 
    180 Now, how about doing something even more useful::
    181 
    182    import argparse
    183    parser = argparse.ArgumentParser()
    184    parser.add_argument("square", help="display a square of a given number")
    185    args = parser.parse_args()
    186    print args.square**2
    187 
    188 Following is a result of running the code:
    189 
    190 .. code-block:: sh
    191 
    192    $ python prog.py 4
    193    Traceback (most recent call last):
    194      File "prog.py", line 5, in <module>
    195        print args.square**2
    196    TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'
    197 
    198 That didn't go so well. That's because :mod:`argparse` treats the options we
    199 give it as strings, unless we tell it otherwise. So, let's tell
    200 :mod:`argparse` to treat that input as an integer::
    201 
    202    import argparse
    203    parser = argparse.ArgumentParser()
    204    parser.add_argument("square", help="display a square of a given number",
    205                        type=int)
    206    args = parser.parse_args()
    207    print args.square**2
    208 
    209 Following is a result of running the code:
    210 
    211 .. code-block:: sh
    212 
    213    $ python prog.py 4
    214    16
    215    $ python prog.py four
    216    usage: prog.py [-h] square
    217    prog.py: error: argument square: invalid int value: 'four'
    218 
    219 That went well. The program now even helpfully quits on bad illegal input
    220 before proceeding.
    221 
    222 
    223 Introducing Optional arguments
    224 ==============================
    225 
    226 So far we have been playing with positional arguments. Let us
    227 have a look on how to add optional ones::
    228 
    229    import argparse
    230    parser = argparse.ArgumentParser()
    231    parser.add_argument("--verbosity", help="increase output verbosity")
    232    args = parser.parse_args()
    233    if args.verbosity:
    234        print "verbosity turned on"
    235 
    236 And the output:
    237 
    238 .. code-block:: sh
    239 
    240    $ python prog.py --verbosity 1
    241    verbosity turned on
    242    $ python prog.py
    243    $ python prog.py --help
    244    usage: prog.py [-h] [--verbosity VERBOSITY]
    245 
    246    optional arguments:
    247      -h, --help            show this help message and exit
    248      --verbosity VERBOSITY
    249                            increase output verbosity
    250    $ python prog.py --verbosity
    251    usage: prog.py [-h] [--verbosity VERBOSITY]
    252    prog.py: error: argument --verbosity: expected one argument
    253 
    254 Here is what is happening:
    255 
    256 * The program is written so as to display something when ``--verbosity`` is
    257   specified and display nothing when not.
    258 
    259 * To show that the option is actually optional, there is no error when running
    260   the program without it. Note that by default, if an optional argument isn't
    261   used, the relevant variable, in this case :attr:`args.verbosity`, is
    262   given ``None`` as a value, which is the reason it fails the truth
    263   test of the :keyword:`if` statement.
    264 
    265 * The help message is a bit different.
    266 
    267 * When using the ``--verbosity`` option, one must also specify some value,
    268   any value.
    269 
    270 The above example accepts arbitrary integer values for ``--verbosity``, but for
    271 our simple program, only two values are actually useful, ``True`` or ``False``.
    272 Let's modify the code accordingly::
    273 
    274    import argparse
    275    parser = argparse.ArgumentParser()
    276    parser.add_argument("--verbose", help="increase output verbosity",
    277                        action="store_true")
    278    args = parser.parse_args()
    279    if args.verbose:
    280       print "verbosity turned on"
    281 
    282 And the output:
    283 
    284 .. code-block:: sh
    285 
    286    $ python prog.py --verbose
    287    verbosity turned on
    288    $ python prog.py --verbose 1
    289    usage: prog.py [-h] [--verbose]
    290    prog.py: error: unrecognized arguments: 1
    291    $ python prog.py --help
    292    usage: prog.py [-h] [--verbose]
    293 
    294    optional arguments:
    295      -h, --help  show this help message and exit
    296      --verbose   increase output verbosity
    297 
    298 Here is what is happening:
    299 
    300 * The option is now more of a flag than something that requires a value.
    301   We even changed the name of the option to match that idea.
    302   Note that we now specify a new keyword, ``action``, and give it the value
    303   ``"store_true"``. This means that, if the option is specified,
    304   assign the value ``True`` to :data:`args.verbose`.
    305   Not specifying it implies ``False``.
    306 
    307 * It complains when you specify a value, in true spirit of what flags
    308   actually are.
    309 
    310 * Notice the different help text.
    311 
    312 
    313 Short options
    314 -------------
    315 
    316 If you are familiar with command line usage,
    317 you will notice that I haven't yet touched on the topic of short
    318 versions of the options. It's quite simple::
    319 
    320    import argparse
    321    parser = argparse.ArgumentParser()
    322    parser.add_argument("-v", "--verbose", help="increase output verbosity",
    323                        action="store_true")
    324    args = parser.parse_args()
    325    if args.verbose:
    326        print "verbosity turned on"
    327 
    328 And here goes:
    329 
    330 .. code-block:: sh
    331 
    332    $ python prog.py -v
    333    verbosity turned on
    334    $ python prog.py --help
    335    usage: prog.py [-h] [-v]
    336 
    337    optional arguments:
    338      -h, --help     show this help message and exit
    339      -v, --verbose  increase output verbosity
    340 
    341 Note that the new ability is also reflected in the help text.
    342 
    343 
    344 Combining Positional and Optional arguments
    345 ===========================================
    346 
    347 Our program keeps growing in complexity::
    348 
    349    import argparse
    350    parser = argparse.ArgumentParser()
    351    parser.add_argument("square", type=int,
    352                        help="display a square of a given number")
    353    parser.add_argument("-v", "--verbose", action="store_true",
    354                        help="increase output verbosity")
    355    args = parser.parse_args()
    356    answer = args.square**2
    357    if args.verbose:
    358        print "the square of {} equals {}".format(args.square, answer)
    359    else:
    360        print answer
    361 
    362 And now the output:
    363 
    364 .. code-block:: sh
    365 
    366    $ python prog.py
    367    usage: prog.py [-h] [-v] square
    368    prog.py: error: the following arguments are required: square
    369    $ python prog.py 4
    370    16
    371    $ python prog.py 4 --verbose
    372    the square of 4 equals 16
    373    $ python prog.py --verbose 4
    374    the square of 4 equals 16
    375 
    376 * We've brought back a positional argument, hence the complaint.
    377 
    378 * Note that the order does not matter.
    379 
    380 How about we give this program of ours back the ability to have
    381 multiple verbosity values, and actually get to use them::
    382 
    383    import argparse
    384    parser = argparse.ArgumentParser()
    385    parser.add_argument("square", type=int,
    386                        help="display a square of a given number")
    387    parser.add_argument("-v", "--verbosity", type=int,
    388                        help="increase output verbosity")
    389    args = parser.parse_args()
    390    answer = args.square**2
    391    if args.verbosity == 2:
    392        print "the square of {} equals {}".format(args.square, answer)
    393    elif args.verbosity == 1:
    394        print "{}^2 == {}".format(args.square, answer)
    395    else:
    396        print answer
    397 
    398 And the output:
    399 
    400 .. code-block:: sh
    401 
    402    $ python prog.py 4
    403    16
    404    $ python prog.py 4 -v
    405    usage: prog.py [-h] [-v VERBOSITY] square
    406    prog.py: error: argument -v/--verbosity: expected one argument
    407    $ python prog.py 4 -v 1
    408    4^2 == 16
    409    $ python prog.py 4 -v 2
    410    the square of 4 equals 16
    411    $ python prog.py 4 -v 3
    412    16
    413 
    414 These all look good except the last one, which exposes a bug in our program.
    415 Let's fix it by restricting the values the ``--verbosity`` option can accept::
    416 
    417    import argparse
    418    parser = argparse.ArgumentParser()
    419    parser.add_argument("square", type=int,
    420                        help="display a square of a given number")
    421    parser.add_argument("-v", "--verbosity", type=int, choices=[0, 1, 2],
    422                        help="increase output verbosity")
    423    args = parser.parse_args()
    424    answer = args.square**2
    425    if args.verbosity == 2:
    426        print "the square of {} equals {}".format(args.square, answer)
    427    elif args.verbosity == 1:
    428        print "{}^2 == {}".format(args.square, answer)
    429    else:
    430        print answer
    431 
    432 And the output:
    433 
    434 .. code-block:: sh
    435 
    436    $ python prog.py 4 -v 3
    437    usage: prog.py [-h] [-v {0,1,2}] square
    438    prog.py: error: argument -v/--verbosity: invalid choice: 3 (choose from 0, 1, 2)
    439    $ python prog.py 4 -h
    440    usage: prog.py [-h] [-v {0,1,2}] square
    441 
    442    positional arguments:
    443      square                display a square of a given number
    444 
    445    optional arguments:
    446      -h, --help            show this help message and exit
    447      -v {0,1,2}, --verbosity {0,1,2}
    448                            increase output verbosity
    449 
    450 Note that the change also reflects both in the error message as well as the
    451 help string.
    452 
    453 Now, let's use a different approach of playing with verbosity, which is pretty
    454 common. It also matches the way the CPython executable handles its own
    455 verbosity argument (check the output of ``python --help``)::
    456 
    457    import argparse
    458    parser = argparse.ArgumentParser()
    459    parser.add_argument("square", type=int,
    460                        help="display the square of a given number")
    461    parser.add_argument("-v", "--verbosity", action="count",
    462                        help="increase output verbosity")
    463    args = parser.parse_args()
    464    answer = args.square**2
    465    if args.verbosity == 2:
    466        print "the square of {} equals {}".format(args.square, answer)
    467    elif args.verbosity == 1:
    468        print "{}^2 == {}".format(args.square, answer)
    469    else:
    470        print answer
    471 
    472 We have introduced another action, "count",
    473 to count the number of occurrences of a specific optional arguments:
    474 
    475 .. code-block:: sh
    476 
    477    $ python prog.py 4
    478    16
    479    $ python prog.py 4 -v
    480    4^2 == 16
    481    $ python prog.py 4 -vv
    482    the square of 4 equals 16
    483    $ python prog.py 4 --verbosity --verbosity
    484    the square of 4 equals 16
    485    $ python prog.py 4 -v 1
    486    usage: prog.py [-h] [-v] square
    487    prog.py: error: unrecognized arguments: 1
    488    $ python prog.py 4 -h
    489    usage: prog.py [-h] [-v] square
    490 
    491    positional arguments:
    492      square           display a square of a given number
    493 
    494    optional arguments:
    495      -h, --help       show this help message and exit
    496      -v, --verbosity  increase output verbosity
    497    $ python prog.py 4 -vvv
    498    16
    499 
    500 * Yes, it's now more of a flag (similar to ``action="store_true"``) in the
    501   previous version of our script. That should explain the complaint.
    502 
    503 * It also behaves similar to "store_true" action.
    504 
    505 * Now here's a demonstration of what the "count" action gives. You've probably
    506   seen this sort of usage before.
    507 
    508 * And, just like the "store_true" action, if you don't specify the ``-v`` flag,
    509   that flag is considered to have ``None`` value.
    510 
    511 * As should be expected, specifying the long form of the flag, we should get
    512   the same output.
    513 
    514 * Sadly, our help output isn't very informative on the new ability our script
    515   has acquired, but that can always be fixed by improving the documentation for
    516   our script (e.g. via the ``help`` keyword argument).
    517 
    518 * That last output exposes a bug in our program.
    519 
    520 
    521 Let's fix::
    522 
    523    import argparse
    524    parser = argparse.ArgumentParser()
    525    parser.add_argument("square", type=int,
    526                        help="display a square of a given number")
    527    parser.add_argument("-v", "--verbosity", action="count",
    528                        help="increase output verbosity")
    529    args = parser.parse_args()
    530    answer = args.square**2
    531 
    532    # bugfix: replace == with >=
    533    if args.verbosity >= 2:
    534        print "the square of {} equals {}".format(args.square, answer)
    535    elif args.verbosity >= 1:
    536        print "{}^2 == {}".format(args.square, answer)
    537    else:
    538        print answer
    539 
    540 And this is what it gives:
    541 
    542 .. code-block:: sh
    543 
    544    $ python prog.py 4 -vvv
    545    the square of 4 equals 16
    546    $ python prog.py 4 -vvvv
    547    the square of 4 equals 16
    548    $ python prog.py 4
    549    Traceback (most recent call last):
    550      File "prog.py", line 11, in <module>
    551        if args.verbosity >= 2:
    552    TypeError: unorderable types: NoneType() >= int()
    553 
    554 * First output went well, and fixes the bug we had before.
    555   That is, we want any value >= 2 to be as verbose as possible.
    556 
    557 * Third output not so good.
    558 
    559 Let's fix that bug::
    560 
    561    import argparse
    562    parser = argparse.ArgumentParser()
    563    parser.add_argument("square", type=int,
    564                        help="display a square of a given number")
    565    parser.add_argument("-v", "--verbosity", action="count", default=0,
    566                        help="increase output verbosity")
    567    args = parser.parse_args()
    568    answer = args.square**2
    569    if args.verbosity >= 2:
    570        print "the square of {} equals {}".format(args.square, answer)
    571    elif args.verbosity >= 1:
    572        print "{}^2 == {}".format(args.square, answer)
    573    else:
    574        print answer
    575 
    576 We've just introduced yet another keyword, ``default``.
    577 We've set it to ``0`` in order to make it comparable to the other int values.
    578 Remember that by default,
    579 if an optional argument isn't specified,
    580 it gets the ``None`` value, and that cannot be compared to an int value
    581 (hence the :exc:`TypeError` exception).
    582 
    583 And:
    584 
    585 .. code-block:: sh
    586 
    587    $ python prog.py 4
    588    16
    589 
    590 You can go quite far just with what we've learned so far,
    591 and we have only scratched the surface.
    592 The :mod:`argparse` module is very powerful,
    593 and we'll explore a bit more of it before we end this tutorial.
    594 
    595 
    596 Getting a little more advanced
    597 ==============================
    598 
    599 What if we wanted to expand our tiny program to perform other powers,
    600 not just squares::
    601 
    602    import argparse
    603    parser = argparse.ArgumentParser()
    604    parser.add_argument("x", type=int, help="the base")
    605    parser.add_argument("y", type=int, help="the exponent")
    606    parser.add_argument("-v", "--verbosity", action="count", default=0)
    607    args = parser.parse_args()
    608    answer = args.x**args.y
    609    if args.verbosity >= 2:
    610        print "{} to the power {} equals {}".format(args.x, args.y, answer)
    611    elif args.verbosity >= 1:
    612        print "{}^{} == {}".format(args.x, args.y, answer)
    613    else:
    614        print answer
    615 
    616 Output:
    617 
    618 .. code-block:: sh
    619 
    620    $ python prog.py
    621    usage: prog.py [-h] [-v] x y
    622    prog.py: error: the following arguments are required: x, y
    623    $ python prog.py -h
    624    usage: prog.py [-h] [-v] x y
    625 
    626    positional arguments:
    627      x                the base
    628      y                the exponent
    629 
    630    optional arguments:
    631      -h, --help       show this help message and exit
    632      -v, --verbosity
    633    $ python prog.py 4 2 -v
    634    4^2 == 16
    635 
    636 
    637 Notice that so far we've been using verbosity level to *change* the text
    638 that gets displayed. The following example instead uses verbosity level
    639 to display *more* text instead::
    640 
    641    import argparse
    642    parser = argparse.ArgumentParser()
    643    parser.add_argument("x", type=int, help="the base")
    644    parser.add_argument("y", type=int, help="the exponent")
    645    parser.add_argument("-v", "--verbosity", action="count", default=0)
    646    args = parser.parse_args()
    647    answer = args.x**args.y
    648    if args.verbosity >= 2:
    649        print "Running '{}'".format(__file__)
    650    if args.verbosity >= 1:
    651        print "{}^{} ==".format(args.x, args.y),
    652    print answer
    653 
    654 Output:
    655 
    656 .. code-block:: sh
    657 
    658    $ python prog.py 4 2
    659    16
    660    $ python prog.py 4 2 -v
    661    4^2 == 16
    662    $ python prog.py 4 2 -vv
    663    Running 'prog.py'
    664    4^2 == 16
    665 
    666 
    667 Conflicting options
    668 -------------------
    669 
    670 So far, we have been working with two methods of an
    671 :class:`argparse.ArgumentParser` instance. Let's introduce a third one,
    672 :meth:`add_mutually_exclusive_group`. It allows for us to specify options that
    673 conflict with each other. Let's also change the rest of the program so that
    674 the new functionality makes more sense:
    675 we'll introduce the ``--quiet`` option,
    676 which will be the opposite of the ``--verbose`` one::
    677 
    678    import argparse
    679 
    680    parser = argparse.ArgumentParser()
    681    group = parser.add_mutually_exclusive_group()
    682    group.add_argument("-v", "--verbose", action="store_true")
    683    group.add_argument("-q", "--quiet", action="store_true")
    684    parser.add_argument("x", type=int, help="the base")
    685    parser.add_argument("y", type=int, help="the exponent")
    686    args = parser.parse_args()
    687    answer = args.x**args.y
    688 
    689    if args.quiet:
    690        print answer
    691    elif args.verbose:
    692        print "{} to the power {} equals {}".format(args.x, args.y, answer)
    693    else:
    694        print "{}^{} == {}".format(args.x, args.y, answer)
    695 
    696 Our program is now simpler, and we've lost some functionality for the sake of
    697 demonstration. Anyways, here's the output:
    698 
    699 .. code-block:: sh
    700 
    701    $ python prog.py 4 2
    702    4^2 == 16
    703    $ python prog.py 4 2 -q
    704    16
    705    $ python prog.py 4 2 -v
    706    4 to the power 2 equals 16
    707    $ python prog.py 4 2 -vq
    708    usage: prog.py [-h] [-v | -q] x y
    709    prog.py: error: argument -q/--quiet: not allowed with argument -v/--verbose
    710    $ python prog.py 4 2 -v --quiet
    711    usage: prog.py [-h] [-v | -q] x y
    712    prog.py: error: argument -q/--quiet: not allowed with argument -v/--verbose
    713 
    714 That should be easy to follow. I've added that last output so you can see the
    715 sort of flexibility you get, i.e. mixing long form options with short form
    716 ones.
    717 
    718 Before we conclude, you probably want to tell your users the main purpose of
    719 your program, just in case they don't know::
    720 
    721    import argparse
    722 
    723    parser = argparse.ArgumentParser(description="calculate X to the power of Y")
    724    group = parser.add_mutually_exclusive_group()
    725    group.add_argument("-v", "--verbose", action="store_true")
    726    group.add_argument("-q", "--quiet", action="store_true")
    727    parser.add_argument("x", type=int, help="the base")
    728    parser.add_argument("y", type=int, help="the exponent")
    729    args = parser.parse_args()
    730    answer = args.x**args.y
    731 
    732    if args.quiet:
    733        print answer
    734    elif args.verbose:
    735        print "{} to the power {} equals {}".format(args.x, args.y, answer)
    736    else:
    737        print "{}^{} == {}".format(args.x, args.y, answer)
    738 
    739 Note that slight difference in the usage text. Note the ``[-v | -q]``,
    740 which tells us that we can either use ``-v`` or ``-q``,
    741 but not both at the same time:
    742 
    743 .. code-block:: sh
    744 
    745    $ python prog.py --help
    746    usage: prog.py [-h] [-v | -q] x y
    747 
    748    calculate X to the power of Y
    749 
    750    positional arguments:
    751      x              the base
    752      y              the exponent
    753 
    754    optional arguments:
    755      -h, --help     show this help message and exit
    756      -v, --verbose
    757      -q, --quiet
    758 
    759 
    760 Conclusion
    761 ==========
    762 
    763 The :mod:`argparse` module offers a lot more than shown here.
    764 Its docs are quite detailed and thorough, and full of examples.
    765 Having gone through this tutorial, you should easily digest them
    766 without feeling overwhelmed.
    767