~dkuhlman/python-training-materials/Materials

« back to all changes in this revision

Viewing changes to python-3.5.1-docs-html/_sources/howto/argparse.txt

  • Committer: Dave Kuhlman
  • Date: 2017-04-15 16:24:56 UTC
  • Revision ID: dkuhlman@davekuhlman.org-20170415162456-iav9vozzg4iwqwv3
Updated docs

Show diffs side-by-side

added added

removed removed

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