blob: 63b0b28abc27d2b1d7b9a3a320f8def6aa974464 [file] [log] [blame]
Georg Brandlc5288e62012-05-06 21:39:35 +02001*****************
2Argparse Tutorial
3*****************
Ezio Melottie48daea2012-05-06 16:15:35 +03004
Benjamin Peterson830b4a82013-01-03 20:34:19 -08005:author: Tshepang Lekhonkhobe
Ezio Melottie48daea2012-05-06 16:15:35 +03006
7.. _argparse-tutorial:
8
9This tutorial is intended to be a gentle introduction to :mod:`argparse`, the
10recommended command-line parsing module in the Python standard library.
Terry Jan Reedyed918832014-10-22 17:59:53 -040011This was written for argparse in Python 3. A few details are different in 2.x,
12especially some exception messages, which were improved in 3.x.
Ezio Melottie48daea2012-05-06 16:15:35 +030013
14.. note::
15
Andrew Svetlov42777cd2013-04-05 10:10:27 +030016 There are two other modules that fulfill the same task, namely
Ezio Melottie48daea2012-05-06 16:15:35 +030017 :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
23Concepts
24========
25
26Let's show the sort of functionality that we are going to explore in this
27introductory 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
48A 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
Georg Brandl090588e2013-10-08 21:54:37 +020068 how it works simply by reading its help text.
Ezio Melottie48daea2012-05-06 16:15:35 +030069
70
71The basics
72==========
73
74Let us start with a very simple example which does (almost) nothing::
75
76 import argparse
77 parser = argparse.ArgumentParser()
78 parser.parse_args()
79
80Following is a result of running the code:
81
82.. code-block:: sh
83
Ezio Melotti1c96f942012-05-06 17:03:19 +030084 $ python prog.py
85 $ python prog.py --help
Ezio Melottie48daea2012-05-06 16:15:35 +030086 usage: prog.py [-h]
87
88 optional arguments:
Ezio Melotti1c96f942012-05-06 17:03:19 +030089 -h, --help show this help message and exit
90 $ python prog.py --verbose
Ezio Melottie48daea2012-05-06 16:15:35 +030091 usage: prog.py [-h]
92 prog.py: error: unrecognized arguments: --verbose
Ezio Melotti1c96f942012-05-06 17:03:19 +030093 $ python prog.py foo
Ezio Melottie48daea2012-05-06 16:15:35 +030094 usage: prog.py [-h]
95 prog.py: error: unrecognized arguments: foo
96
97Here 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
111Introducing Positional arguments
112================================
113
114An example::
115
116 import argparse
117 parser = argparse.ArgumentParser()
118 parser.add_argument("echo")
119 args = parser.parse_args()
Ezio Melotti1c96f942012-05-06 17:03:19 +0300120 print args.echo
Ezio Melottie48daea2012-05-06 16:15:35 +0300121
122And running the code:
123
124.. code-block:: sh
125
Ezio Melotti1c96f942012-05-06 17:03:19 +0300126 $ python prog.py
Ezio Melottie48daea2012-05-06 16:15:35 +0300127 usage: prog.py [-h] echo
128 prog.py: error: the following arguments are required: echo
Ezio Melotti1c96f942012-05-06 17:03:19 +0300129 $ python prog.py --help
Ezio Melottie48daea2012-05-06 16:15:35 +0300130 usage: prog.py [-h] echo
131
132 positional arguments:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300133 echo
Ezio Melottie48daea2012-05-06 16:15:35 +0300134
135 optional arguments:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300136 -h, --help show this help message and exit
137 $ python prog.py foo
Ezio Melottie48daea2012-05-06 16:15:35 +0300138 foo
139
140Here 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
156Note however that, although the help display looks nice and all, it currently
157is not as helpful as it can be. For example we see that we got ``echo`` as a
158positional argument, but we don't know what it does, other than by guessing or
159by 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()
Ezio Melotti1c96f942012-05-06 17:03:19 +0300165 print args.echo
Ezio Melottie48daea2012-05-06 16:15:35 +0300166
167And we get:
168
169.. code-block:: sh
170
Ezio Melotti1c96f942012-05-06 17:03:19 +0300171 $ python prog.py -h
Ezio Melottie48daea2012-05-06 16:15:35 +0300172 usage: prog.py [-h] echo
173
174 positional arguments:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300175 echo echo the string you use here
Ezio Melottie48daea2012-05-06 16:15:35 +0300176
177 optional arguments:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300178 -h, --help show this help message and exit
Ezio Melottie48daea2012-05-06 16:15:35 +0300179
180Now, 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()
Ezio Melotti1c96f942012-05-06 17:03:19 +0300186 print args.square**2
Ezio Melottie48daea2012-05-06 16:15:35 +0300187
188Following is a result of running the code:
189
190.. code-block:: sh
191
Ezio Melotti1c96f942012-05-06 17:03:19 +0300192 $ python prog.py 4
Ezio Melottie48daea2012-05-06 16:15:35 +0300193 Traceback (most recent call last):
Ezio Melotti1c96f942012-05-06 17:03:19 +0300194 File "prog.py", line 5, in <module>
195 print args.square**2
Ezio Melottie48daea2012-05-06 16:15:35 +0300196 TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'
197
198That didn't go so well. That's because :mod:`argparse` treats the options we
199give 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",
Ezio Melotti1c96f942012-05-06 17:03:19 +0300205 type=int)
Ezio Melottie48daea2012-05-06 16:15:35 +0300206 args = parser.parse_args()
Ezio Melotti1c96f942012-05-06 17:03:19 +0300207 print args.square**2
Ezio Melottie48daea2012-05-06 16:15:35 +0300208
209Following is a result of running the code:
210
211.. code-block:: sh
212
Ezio Melotti1c96f942012-05-06 17:03:19 +0300213 $ python prog.py 4
Ezio Melottie48daea2012-05-06 16:15:35 +0300214 16
Ezio Melotti1c96f942012-05-06 17:03:19 +0300215 $ python prog.py four
Ezio Melottie48daea2012-05-06 16:15:35 +0300216 usage: prog.py [-h] square
217 prog.py: error: argument square: invalid int value: 'four'
218
219That went well. The program now even helpfully quits on bad illegal input
220before proceeding.
221
222
223Introducing Optional arguments
224==============================
225
Berker Peksagfb123652017-04-20 07:41:01 +0300226So far we have been playing with positional arguments. Let us
Ezio Melottie48daea2012-05-06 16:15:35 +0300227have 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:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300234 print "verbosity turned on"
Ezio Melottie48daea2012-05-06 16:15:35 +0300235
236And the output:
237
238.. code-block:: sh
239
Ezio Melotti1c96f942012-05-06 17:03:19 +0300240 $ python prog.py --verbosity 1
Ezio Melottie48daea2012-05-06 16:15:35 +0300241 verbosity turned on
Ezio Melotti1c96f942012-05-06 17:03:19 +0300242 $ python prog.py
243 $ python prog.py --help
Ezio Melottie48daea2012-05-06 16:15:35 +0300244 usage: prog.py [-h] [--verbosity VERBOSITY]
245
246 optional arguments:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300247 -h, --help show this help message and exit
248 --verbosity VERBOSITY
Ezio Melottie48daea2012-05-06 16:15:35 +0300249 increase output verbosity
Ezio Melotti1c96f942012-05-06 17:03:19 +0300250 $ python prog.py --verbosity
Ezio Melottie48daea2012-05-06 16:15:35 +0300251 usage: prog.py [-h] [--verbosity VERBOSITY]
252 prog.py: error: argument --verbosity: expected one argument
253
254Here 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
270The above example accepts arbitrary integer values for ``--verbosity``, but for
271our simple program, only two values are actually useful, ``True`` or ``False``.
272Let's modify the code accordingly::
273
274 import argparse
275 parser = argparse.ArgumentParser()
276 parser.add_argument("--verbose", help="increase output verbosity",
Ezio Melotti1c96f942012-05-06 17:03:19 +0300277 action="store_true")
Ezio Melottie48daea2012-05-06 16:15:35 +0300278 args = parser.parse_args()
279 if args.verbose:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300280 print "verbosity turned on"
Ezio Melottie48daea2012-05-06 16:15:35 +0300281
282And the output:
283
284.. code-block:: sh
285
Ezio Melotti1c96f942012-05-06 17:03:19 +0300286 $ python prog.py --verbose
Ezio Melottie48daea2012-05-06 16:15:35 +0300287 verbosity turned on
Ezio Melotti1c96f942012-05-06 17:03:19 +0300288 $ python prog.py --verbose 1
Ezio Melottie48daea2012-05-06 16:15:35 +0300289 usage: prog.py [-h] [--verbose]
290 prog.py: error: unrecognized arguments: 1
Ezio Melotti1c96f942012-05-06 17:03:19 +0300291 $ python prog.py --help
Ezio Melottie48daea2012-05-06 16:15:35 +0300292 usage: prog.py [-h] [--verbose]
293
294 optional arguments:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300295 -h, --help show this help message and exit
296 --verbose increase output verbosity
Ezio Melottie48daea2012-05-06 16:15:35 +0300297
298Here 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
313Short options
314-------------
315
316If you are familiar with command line usage,
317you will notice that I haven't yet touched on the topic of short
318versions 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",
Ezio Melotti1c96f942012-05-06 17:03:19 +0300323 action="store_true")
Ezio Melottie48daea2012-05-06 16:15:35 +0300324 args = parser.parse_args()
325 if args.verbose:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300326 print "verbosity turned on"
Ezio Melottie48daea2012-05-06 16:15:35 +0300327
328And here goes:
329
330.. code-block:: sh
331
Ezio Melotti1c96f942012-05-06 17:03:19 +0300332 $ python prog.py -v
Ezio Melottie48daea2012-05-06 16:15:35 +0300333 verbosity turned on
Ezio Melotti1c96f942012-05-06 17:03:19 +0300334 $ python prog.py --help
Ezio Melottie48daea2012-05-06 16:15:35 +0300335 usage: prog.py [-h] [-v]
336
337 optional arguments:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300338 -h, --help show this help message and exit
339 -v, --verbose increase output verbosity
Ezio Melottie48daea2012-05-06 16:15:35 +0300340
341Note that the new ability is also reflected in the help text.
342
343
344Combining Positional and Optional arguments
345===========================================
346
347Our program keeps growing in complexity::
348
349 import argparse
350 parser = argparse.ArgumentParser()
351 parser.add_argument("square", type=int,
Ezio Melotti1c96f942012-05-06 17:03:19 +0300352 help="display a square of a given number")
Ezio Melottie48daea2012-05-06 16:15:35 +0300353 parser.add_argument("-v", "--verbose", action="store_true",
Ezio Melotti1c96f942012-05-06 17:03:19 +0300354 help="increase output verbosity")
Ezio Melottie48daea2012-05-06 16:15:35 +0300355 args = parser.parse_args()
356 answer = args.square**2
357 if args.verbose:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300358 print "the square of {} equals {}".format(args.square, answer)
Ezio Melottie48daea2012-05-06 16:15:35 +0300359 else:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300360 print answer
Ezio Melottie48daea2012-05-06 16:15:35 +0300361
362And now the output:
363
364.. code-block:: sh
365
Ezio Melotti1c96f942012-05-06 17:03:19 +0300366 $ python prog.py
Ezio Melottie48daea2012-05-06 16:15:35 +0300367 usage: prog.py [-h] [-v] square
368 prog.py: error: the following arguments are required: square
Ezio Melotti1c96f942012-05-06 17:03:19 +0300369 $ python prog.py 4
Ezio Melottie48daea2012-05-06 16:15:35 +0300370 16
Ezio Melotti1c96f942012-05-06 17:03:19 +0300371 $ python prog.py 4 --verbose
Ezio Melottie48daea2012-05-06 16:15:35 +0300372 the square of 4 equals 16
Ezio Melotti1c96f942012-05-06 17:03:19 +0300373 $ python prog.py --verbose 4
Ezio Melottie48daea2012-05-06 16:15:35 +0300374 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
380How about we give this program of ours back the ability to have
381multiple verbosity values, and actually get to use them::
382
383 import argparse
384 parser = argparse.ArgumentParser()
385 parser.add_argument("square", type=int,
Ezio Melotti1c96f942012-05-06 17:03:19 +0300386 help="display a square of a given number")
Ezio Melottie48daea2012-05-06 16:15:35 +0300387 parser.add_argument("-v", "--verbosity", type=int,
Ezio Melotti1c96f942012-05-06 17:03:19 +0300388 help="increase output verbosity")
Ezio Melottie48daea2012-05-06 16:15:35 +0300389 args = parser.parse_args()
390 answer = args.square**2
391 if args.verbosity == 2:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300392 print "the square of {} equals {}".format(args.square, answer)
Ezio Melottie48daea2012-05-06 16:15:35 +0300393 elif args.verbosity == 1:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300394 print "{}^2 == {}".format(args.square, answer)
Ezio Melottie48daea2012-05-06 16:15:35 +0300395 else:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300396 print answer
Ezio Melottie48daea2012-05-06 16:15:35 +0300397
398And the output:
399
400.. code-block:: sh
401
Ezio Melotti1c96f942012-05-06 17:03:19 +0300402 $ python prog.py 4
Ezio Melottie48daea2012-05-06 16:15:35 +0300403 16
Ezio Melotti1c96f942012-05-06 17:03:19 +0300404 $ python prog.py 4 -v
Ezio Melottie48daea2012-05-06 16:15:35 +0300405 usage: prog.py [-h] [-v VERBOSITY] square
406 prog.py: error: argument -v/--verbosity: expected one argument
Ezio Melotti1c96f942012-05-06 17:03:19 +0300407 $ python prog.py 4 -v 1
Ezio Melottie48daea2012-05-06 16:15:35 +0300408 4^2 == 16
Ezio Melotti1c96f942012-05-06 17:03:19 +0300409 $ python prog.py 4 -v 2
Ezio Melottie48daea2012-05-06 16:15:35 +0300410 the square of 4 equals 16
Ezio Melotti1c96f942012-05-06 17:03:19 +0300411 $ python prog.py 4 -v 3
Ezio Melottie48daea2012-05-06 16:15:35 +0300412 16
413
414These all look good except the last one, which exposes a bug in our program.
415Let'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,
Ezio Melotti1c96f942012-05-06 17:03:19 +0300420 help="display a square of a given number")
Ezio Melottie48daea2012-05-06 16:15:35 +0300421 parser.add_argument("-v", "--verbosity", type=int, choices=[0, 1, 2],
Ezio Melotti1c96f942012-05-06 17:03:19 +0300422 help="increase output verbosity")
Ezio Melottie48daea2012-05-06 16:15:35 +0300423 args = parser.parse_args()
424 answer = args.square**2
425 if args.verbosity == 2:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300426 print "the square of {} equals {}".format(args.square, answer)
Ezio Melottie48daea2012-05-06 16:15:35 +0300427 elif args.verbosity == 1:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300428 print "{}^2 == {}".format(args.square, answer)
Ezio Melottie48daea2012-05-06 16:15:35 +0300429 else:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300430 print answer
Ezio Melottie48daea2012-05-06 16:15:35 +0300431
432And the output:
433
434.. code-block:: sh
435
Ezio Melotti1c96f942012-05-06 17:03:19 +0300436 $ python prog.py 4 -v 3
Ezio Melottie48daea2012-05-06 16:15:35 +0300437 usage: prog.py [-h] [-v {0,1,2}] square
438 prog.py: error: argument -v/--verbosity: invalid choice: 3 (choose from 0, 1, 2)
Ezio Melotti1c96f942012-05-06 17:03:19 +0300439 $ python prog.py 4 -h
Ezio Melottie48daea2012-05-06 16:15:35 +0300440 usage: prog.py [-h] [-v {0,1,2}] square
441
442 positional arguments:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300443 square display a square of a given number
Ezio Melottie48daea2012-05-06 16:15:35 +0300444
445 optional arguments:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300446 -h, --help show this help message and exit
447 -v {0,1,2}, --verbosity {0,1,2}
Ezio Melottie48daea2012-05-06 16:15:35 +0300448 increase output verbosity
449
450Note that the change also reflects both in the error message as well as the
451help string.
452
453Now, let's use a different approach of playing with verbosity, which is pretty
454common. It also matches the way the CPython executable handles its own
455verbosity argument (check the output of ``python --help``)::
456
457 import argparse
458 parser = argparse.ArgumentParser()
459 parser.add_argument("square", type=int,
Ezio Melotti1c96f942012-05-06 17:03:19 +0300460 help="display the square of a given number")
Ezio Melottie48daea2012-05-06 16:15:35 +0300461 parser.add_argument("-v", "--verbosity", action="count",
Ezio Melotti1c96f942012-05-06 17:03:19 +0300462 help="increase output verbosity")
Ezio Melottie48daea2012-05-06 16:15:35 +0300463 args = parser.parse_args()
464 answer = args.square**2
465 if args.verbosity == 2:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300466 print "the square of {} equals {}".format(args.square, answer)
Ezio Melottie48daea2012-05-06 16:15:35 +0300467 elif args.verbosity == 1:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300468 print "{}^2 == {}".format(args.square, answer)
Ezio Melottie48daea2012-05-06 16:15:35 +0300469 else:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300470 print answer
Ezio Melottie48daea2012-05-06 16:15:35 +0300471
472We have introduced another action, "count",
Ned Deilyc967a592013-07-14 12:42:27 -0700473to count the number of occurrences of a specific optional arguments:
Ezio Melottie48daea2012-05-06 16:15:35 +0300474
475.. code-block:: sh
476
Ezio Melotti1c96f942012-05-06 17:03:19 +0300477 $ python prog.py 4
Ezio Melottie48daea2012-05-06 16:15:35 +0300478 16
Ezio Melotti1c96f942012-05-06 17:03:19 +0300479 $ python prog.py 4 -v
Ezio Melottie48daea2012-05-06 16:15:35 +0300480 4^2 == 16
Ezio Melotti1c96f942012-05-06 17:03:19 +0300481 $ python prog.py 4 -vv
Ezio Melottie48daea2012-05-06 16:15:35 +0300482 the square of 4 equals 16
Ezio Melotti1c96f942012-05-06 17:03:19 +0300483 $ python prog.py 4 --verbosity --verbosity
Ezio Melottie48daea2012-05-06 16:15:35 +0300484 the square of 4 equals 16
Ezio Melotti1c96f942012-05-06 17:03:19 +0300485 $ python prog.py 4 -v 1
Ezio Melottie48daea2012-05-06 16:15:35 +0300486 usage: prog.py [-h] [-v] square
487 prog.py: error: unrecognized arguments: 1
Ezio Melotti1c96f942012-05-06 17:03:19 +0300488 $ python prog.py 4 -h
Ezio Melottie48daea2012-05-06 16:15:35 +0300489 usage: prog.py [-h] [-v] square
490
491 positional arguments:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300492 square display a square of a given number
Ezio Melottie48daea2012-05-06 16:15:35 +0300493
494 optional arguments:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300495 -h, --help show this help message and exit
496 -v, --verbosity increase output verbosity
497 $ python prog.py 4 -vvv
Ezio Melottie48daea2012-05-06 16:15:35 +0300498 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
Georg Brandl97b6e0b2016-02-28 21:09:36 +0100516 our script (e.g. via the ``help`` keyword argument).
Ezio Melottie48daea2012-05-06 16:15:35 +0300517
518* That last output exposes a bug in our program.
519
520
521Let's fix::
522
523 import argparse
524 parser = argparse.ArgumentParser()
525 parser.add_argument("square", type=int,
Ezio Melotti1c96f942012-05-06 17:03:19 +0300526 help="display a square of a given number")
Ezio Melottie48daea2012-05-06 16:15:35 +0300527 parser.add_argument("-v", "--verbosity", action="count",
Ezio Melotti1c96f942012-05-06 17:03:19 +0300528 help="increase output verbosity")
Ezio Melottie48daea2012-05-06 16:15:35 +0300529 args = parser.parse_args()
530 answer = args.square**2
531
532 # bugfix: replace == with >=
533 if args.verbosity >= 2:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300534 print "the square of {} equals {}".format(args.square, answer)
Ezio Melottie48daea2012-05-06 16:15:35 +0300535 elif args.verbosity >= 1:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300536 print "{}^2 == {}".format(args.square, answer)
Ezio Melottie48daea2012-05-06 16:15:35 +0300537 else:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300538 print answer
Ezio Melottie48daea2012-05-06 16:15:35 +0300539
540And this is what it gives:
541
542.. code-block:: sh
543
Ezio Melotti1c96f942012-05-06 17:03:19 +0300544 $ python prog.py 4 -vvv
Ezio Melottie48daea2012-05-06 16:15:35 +0300545 the square of 4 equals 16
Ezio Melotti1c96f942012-05-06 17:03:19 +0300546 $ python prog.py 4 -vvvv
Ezio Melottie48daea2012-05-06 16:15:35 +0300547 the square of 4 equals 16
Ezio Melotti1c96f942012-05-06 17:03:19 +0300548 $ python prog.py 4
Ezio Melottie48daea2012-05-06 16:15:35 +0300549 Traceback (most recent call last):
Ezio Melotti1c96f942012-05-06 17:03:19 +0300550 File "prog.py", line 11, in <module>
551 if args.verbosity >= 2:
Ezio Melottie48daea2012-05-06 16:15:35 +0300552 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
559Let's fix that bug::
560
561 import argparse
562 parser = argparse.ArgumentParser()
563 parser.add_argument("square", type=int,
Ezio Melotti1c96f942012-05-06 17:03:19 +0300564 help="display a square of a given number")
Ezio Melottie48daea2012-05-06 16:15:35 +0300565 parser.add_argument("-v", "--verbosity", action="count", default=0,
Ezio Melotti1c96f942012-05-06 17:03:19 +0300566 help="increase output verbosity")
Ezio Melottie48daea2012-05-06 16:15:35 +0300567 args = parser.parse_args()
568 answer = args.square**2
569 if args.verbosity >= 2:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300570 print "the square of {} equals {}".format(args.square, answer)
Ezio Melottie48daea2012-05-06 16:15:35 +0300571 elif args.verbosity >= 1:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300572 print "{}^2 == {}".format(args.square, answer)
Ezio Melottie48daea2012-05-06 16:15:35 +0300573 else:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300574 print answer
Ezio Melottie48daea2012-05-06 16:15:35 +0300575
576We've just introduced yet another keyword, ``default``.
577We've set it to ``0`` in order to make it comparable to the other int values.
578Remember that by default,
579if an optional argument isn't specified,
580it gets the ``None`` value, and that cannot be compared to an int value
581(hence the :exc:`TypeError` exception).
582
583And:
584
585.. code-block:: sh
586
Ezio Melotti1c96f942012-05-06 17:03:19 +0300587 $ python prog.py 4
Ezio Melottie48daea2012-05-06 16:15:35 +0300588 16
589
590You can go quite far just with what we've learned so far,
591and we have only scratched the surface.
592The :mod:`argparse` module is very powerful,
593and we'll explore a bit more of it before we end this tutorial.
594
595
596Getting a little more advanced
597==============================
598
599What if we wanted to expand our tiny program to perform other powers,
600not 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:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300610 print "{} to the power {} equals {}".format(args.x, args.y, answer)
Ezio Melottie48daea2012-05-06 16:15:35 +0300611 elif args.verbosity >= 1:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300612 print "{}^{} == {}".format(args.x, args.y, answer)
Ezio Melottie48daea2012-05-06 16:15:35 +0300613 else:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300614 print answer
Ezio Melottie48daea2012-05-06 16:15:35 +0300615
616Output:
617
618.. code-block:: sh
619
Ezio Melotti1c96f942012-05-06 17:03:19 +0300620 $ python prog.py
Ezio Melottie48daea2012-05-06 16:15:35 +0300621 usage: prog.py [-h] [-v] x y
622 prog.py: error: the following arguments are required: x, y
Ezio Melotti1c96f942012-05-06 17:03:19 +0300623 $ python prog.py -h
Ezio Melottie48daea2012-05-06 16:15:35 +0300624 usage: prog.py [-h] [-v] x y
625
626 positional arguments:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300627 x the base
628 y the exponent
Ezio Melottie48daea2012-05-06 16:15:35 +0300629
630 optional arguments:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300631 -h, --help show this help message and exit
632 -v, --verbosity
633 $ python prog.py 4 2 -v
Ezio Melottie48daea2012-05-06 16:15:35 +0300634 4^2 == 16
635
636
637Notice that so far we've been using verbosity level to *change* the text
638that gets displayed. The following example instead uses verbosity level
639to 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:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300649 print "Running '{}'".format(__file__)
Ezio Melottie48daea2012-05-06 16:15:35 +0300650 if args.verbosity >= 1:
Ezio Melottie608e312012-07-13 21:40:25 +0200651 print "{}^{} ==".format(args.x, args.y),
Ezio Melotti1c96f942012-05-06 17:03:19 +0300652 print answer
Ezio Melottie48daea2012-05-06 16:15:35 +0300653
654Output:
655
656.. code-block:: sh
657
Ezio Melotti1c96f942012-05-06 17:03:19 +0300658 $ python prog.py 4 2
Ezio Melottie48daea2012-05-06 16:15:35 +0300659 16
Ezio Melotti1c96f942012-05-06 17:03:19 +0300660 $ python prog.py 4 2 -v
Ezio Melottie48daea2012-05-06 16:15:35 +0300661 4^2 == 16
Ezio Melotti1c96f942012-05-06 17:03:19 +0300662 $ python prog.py 4 2 -vv
Ezio Melottie48daea2012-05-06 16:15:35 +0300663 Running 'prog.py'
664 4^2 == 16
665
666
667Conflicting options
668-------------------
669
670So 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
Andrew Svetlov9c6eb262013-04-06 18:54:19 +0300673conflict with each other. Let's also change the rest of the program so that
674the new functionality makes more sense:
Ezio Melottie48daea2012-05-06 16:15:35 +0300675we'll introduce the ``--quiet`` option,
676which 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:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300690 print answer
Ezio Melottie48daea2012-05-06 16:15:35 +0300691 elif args.verbose:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300692 print "{} to the power {} equals {}".format(args.x, args.y, answer)
Ezio Melottie48daea2012-05-06 16:15:35 +0300693 else:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300694 print "{}^{} == {}".format(args.x, args.y, answer)
Ezio Melottie48daea2012-05-06 16:15:35 +0300695
696Our program is now simpler, and we've lost some functionality for the sake of
697demonstration. Anyways, here's the output:
698
699.. code-block:: sh
700
Ezio Melotti1c96f942012-05-06 17:03:19 +0300701 $ python prog.py 4 2
Ezio Melottie48daea2012-05-06 16:15:35 +0300702 4^2 == 16
Ezio Melotti1c96f942012-05-06 17:03:19 +0300703 $ python prog.py 4 2 -q
Ezio Melottie48daea2012-05-06 16:15:35 +0300704 16
Ezio Melotti1c96f942012-05-06 17:03:19 +0300705 $ python prog.py 4 2 -v
Ezio Melottie48daea2012-05-06 16:15:35 +0300706 4 to the power 2 equals 16
Ezio Melotti1c96f942012-05-06 17:03:19 +0300707 $ python prog.py 4 2 -vq
Ezio Melottie48daea2012-05-06 16:15:35 +0300708 usage: prog.py [-h] [-v | -q] x y
709 prog.py: error: argument -q/--quiet: not allowed with argument -v/--verbose
Ezio Melotti1c96f942012-05-06 17:03:19 +0300710 $ python prog.py 4 2 -v --quiet
Ezio Melottie48daea2012-05-06 16:15:35 +0300711 usage: prog.py [-h] [-v | -q] x y
712 prog.py: error: argument -q/--quiet: not allowed with argument -v/--verbose
713
714That should be easy to follow. I've added that last output so you can see the
715sort of flexibility you get, i.e. mixing long form options with short form
716ones.
717
718Before we conclude, you probably want to tell your users the main purpose of
719your 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:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300733 print answer
Ezio Melottie48daea2012-05-06 16:15:35 +0300734 elif args.verbose:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300735 print "{} to the power {} equals {}".format(args.x, args.y, answer)
Ezio Melottie48daea2012-05-06 16:15:35 +0300736 else:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300737 print "{}^{} == {}".format(args.x, args.y, answer)
Ezio Melottie48daea2012-05-06 16:15:35 +0300738
739Note that slight difference in the usage text. Note the ``[-v | -q]``,
740which tells us that we can either use ``-v`` or ``-q``,
741but not both at the same time:
742
743.. code-block:: sh
744
Ezio Melotti1c96f942012-05-06 17:03:19 +0300745 $ python prog.py --help
Ezio Melottie48daea2012-05-06 16:15:35 +0300746 usage: prog.py [-h] [-v | -q] x y
747
748 calculate X to the power of Y
749
750 positional arguments:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300751 x the base
752 y the exponent
Ezio Melottie48daea2012-05-06 16:15:35 +0300753
754 optional arguments:
Ezio Melotti1c96f942012-05-06 17:03:19 +0300755 -h, --help show this help message and exit
756 -v, --verbose
757 -q, --quiet
Ezio Melottie48daea2012-05-06 16:15:35 +0300758
759
760Conclusion
761==========
762
763The :mod:`argparse` module offers a lot more than shown here.
764Its docs are quite detailed and thorough, and full of examples.
765Having gone through this tutorial, you should easily digest them
766without feeling overwhelmed.