Skip to content

Commit 5d86774

Browse files
committed
Updates based on review feedback
1 parent 7f51456 commit 5d86774

File tree

5 files changed

+161
-94
lines changed

5 files changed

+161
-94
lines changed

Doc/howto/argparse-optparse.rst

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
.. currentmodule:: argparse
22

33
.. _upgrading-optparse-code:
4+
.. _migrating-optparse-code:
45

5-
==========================
6-
Upgrading optparse code
7-
==========================
6+
============================================
7+
Migrating ``optparse`` code to ``argparse``
8+
============================================
89

910
The :mod:`argparse` module offers several higher level features not natively
1011
provided by the :mod:`optparse` module, including:
@@ -17,13 +18,22 @@ provided by the :mod:`optparse` module, including:
1718
* Providing a much simpler interface for custom ``type`` and ``action``.
1819

1920
Originally, the :mod:`argparse` module attempted to maintain compatibility
20-
with :mod:`optparse`. However, :mod:`optparse` was difficult to extend
21-
transparently, particularly with the changes required to support
22-
``nargs=`` specifiers and better usage messages. When most everything in
23-
:mod:`optparse` had either been copy-pasted over or monkey-patched, it no
24-
longer seemed practical to try to maintain the backwards compatibility.
21+
with :mod:`optparse`. However, the fundamental design differences between
22+
supporting declarative command line option processing (while leaving positional
23+
argument processing to application code), and supporting both named options
24+
and positional arguments in the declarative interface mean that the
25+
API has diverged from that of ``optparse`` over time.
2526

26-
A partial upgrade path from :mod:`optparse` to :mod:`argparse`:
27+
As described in :ref:`choosing-an-argument-parser`, applications that are
28+
currently using :mod:`optparse` and are happy with the way it works can
29+
just continue to use ``optparse``.
30+
31+
Application developers that are considering migrating should also review
32+
the list of intrinsic behavioural differences described in that section
33+
before deciding whether or not migration is desirable.
34+
35+
For applications that do choose to migrate from :mod:`optparse` to :mod:`argparse`,
36+
the following suggestions should be helpful:
2737

2838
* Replace all :meth:`optparse.OptionParser.add_option` calls with
2939
:meth:`ArgumentParser.add_argument` calls.

Doc/howto/argparse.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ recommended command-line parsing module in the Python standard library.
1818
module (which may require more code to configure for a given application,
1919
but also allows an application to request behaviors that ``argparse``
2020
doesn't support), and the very low level :mod:`getopt` (which specifically
21-
serves as an equivalent to :c:func:`!getopt` from the C language).
21+
serves as an equivalent to the :c:func:`!getopt` family of functions
22+
available to C programmers).
2223
While neither of those modules is covered directly in this guide, many of
2324
the core concepts in ``argparse`` first originated in ``optparse``, so
2425
some aspects of this tutorial will also be relevant to ``optparse`` users.

Doc/library/argparse.rst

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,15 @@
1313

1414
.. note::
1515

16-
While :mod:`argparse` is the recommended standard library module for
17-
*implementing* basic command line applications, authors of third party
18-
command line argument processing libraries may find that the
19-
lower level :mod:`optparse` module serves as a better foundation for
20-
that use case. ``optparse`` (or one of the third party libraries
21-
based on it) may also be worth considering for applications where
22-
``argparse`` doesn't support behaviors that the application requires
23-
(such as entirely disabling support for interspersed options and
24-
positional arguments, or stricter adherence to common Unix and Linux
25-
command line interface conventions related to the handling of option
26-
parameter values that start with ``-``).
16+
While :mod:`argparse` is the default recommended standard library module
17+
for implementing basic command line applications, authors with more
18+
exacting requirements for exactly how their command line applications
19+
behave may find it doesn't provide the necessary level of control.
20+
Refer to :ref:`choosing-an-argument-parser` for alternatives to
21+
consider when ``argparse`` doesn't support behaviors that the application
22+
requires (such as entirely disabling support for interspersed options and
23+
positional arguments, or accepting option parameter values that start
24+
with ``-`` even when they correspond to another defined option).
2725

2826
--------------
2927

Doc/library/getopt.rst

Lines changed: 21 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
.. note::
1111

12-
This module is considered feature complete. A more object-oriented and
12+
This module is considered feature complete. A more declarative and
1313
extensible alternative to this API is provided in the :mod:`optparse`
1414
module. Further functional enhancements for command line parameter
1515
processing are provided either as third party modules on PyPI,
@@ -27,7 +27,8 @@ Users who are unfamiliar with the Unix :c:func:`!getopt` function should conside
2727
using the :mod:`argparse` module instead. Users who are familiar with the Unix
2828
:c:func:`!getopt` function, but would like to get equivalent behavior while
2929
writing less code and getting better help and error messages should consider
30-
using the :mod:`optparse` module.
30+
using the :mod:`optparse` module. See :ref:`choosing-an-argument-parser` for
31+
additional details.
3132

3233
This module provides two functions and an
3334
exception:
@@ -215,47 +216,28 @@ and more informative help and error messages by using the :mod:`optparse` module
215216
process(args, output=opts.output, verbose=opts.verbose)
216217

217218
A roughly equivalent command line interface for this case can also be
218-
produced by using the :mod:`argparse` module::
219-
220-
import argparse
221-
222-
if __name__ == '__main__':
223-
parser = argparse.ArgumentParser()
224-
parser.add_argument('-o', '--output')
225-
parser.add_argument('-v', dest='verbose', action='store_true')
226-
parser.add_argument('rest', nargs='*')
227-
args = parser.parse_args()
228-
process(args.rest, output=args.output, verbose=args.verbose)
229-
230-
However, unlike the ``optparse`` example, this ``argparse`` example will
231-
handle some parameter combinations differently from the way the ``getopt``
232-
version would handle them. For example (amongst other differences):
233-
234-
* supplying ``-o -v`` gives ``output="-v"`` and ``verbose=False``
235-
for both ``getopt`` and ``optparse``,
236-
but a usage error with ``argparse``
237-
(complaining that no value has been supplied for ``-o/--output``,
238-
since ``-v`` is interpreted as meaning the verbosity flag)
239-
* similarly, supplying ``-o --`` gives ``output="--"`` and ``args=()``
240-
for both ``getopt`` and ``optparse``,
241-
but a usage error with ``argparse``
242-
(also complaining that no value has been supplied for ``-o/--output``,
243-
since ``--`` is interpreted as terminating the option processing
244-
and treating all remaining values as positional arguments)
245-
* supplying ``-o=foo`` gives ``output="=foo"``
246-
for both ``getopt`` and ``optparse``,
247-
but gives ``output="foo"`` with ``argparse``
248-
(since ``=`` is special cased as an alternative separator for
249-
option parameter values)
250-
251-
Whether these differing behaviors in the ``argparse`` version are
252-
considered desirable or a problem will depend on the specific command line
253-
application use case.
219+
produced by using the :mod:`argparse` module:
220+
221+
.. testcode::
222+
223+
import argparse
224+
225+
if __name__ == '__main__':
226+
parser = argparse.ArgumentParser()
227+
parser.add_argument('-o', '--output')
228+
parser.add_argument('-v', dest='verbose', action='store_true')
229+
parser.add_argument('rest', nargs='*')
230+
args = parser.parse_args()
231+
process(args.rest, output=args.output, verbose=args.verbose)
232+
233+
See :ref:`choosing-an-argument-parser` for details on how the ``argparse``
234+
version of this code differs in behaviour from the ``optparse`` (and
235+
``getopt``) version.
254236

255237
.. seealso::
256238

257239
Module :mod:`optparse`
258-
More object-oriented command line option parsing.
240+
Declarative command line option parsing.
259241

260242
Module :mod:`argparse`
261243
More opinionated command line option and argument parsing library.

Doc/library/optparse.rst

Lines changed: 110 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,41 +3,114 @@
33

44
.. module:: optparse
55
:synopsis: Command-line option parsing library.
6-
:deprecated:
76

87
.. moduleauthor:: Greg Ward <[email protected]>
98
.. sectionauthor:: Greg Ward <[email protected]>
109

1110
**Source code:** :source:`Lib/optparse.py`
1211

13-
.. note::
14-
15-
This module is considered feature complete. Further functional enhancements for
16-
command line parameter processing are provided either as third party modules on
17-
PyPI, or else as features in the :mod:`argparse` module.
18-
19-
.. note::
20-
21-
The higher level :mod:`argparse` (rather than this module) is the recommended
22-
standard library module for implementing command line applications unless one
23-
of the following caveats applies:
24-
25-
* the application requires additional control over the way options and
26-
positional parameters are interleaved on the command line (including
27-
the ability to disable the interleaving feature completely)
28-
* the application requires additional control over the incremental parsing
29-
of command line elements (while ``argparse`` does support this, the
30-
exact way it works in practice is undesirable for some use cases)
31-
* the application requires additional control over the handling of options
32-
which accept parameter values that may start with ``-`` (such as delegated
33-
options to be passed to invoked subprocesses)
34-
* the application requires some other command line parameter processing
35-
behavior which ``argparse`` does not support, but which can be implemented
36-
in terms of the lower level interface offered by ``optparse``
12+
--------------
3713

38-
These ``argparse`` caveats also mean that :mod:`optparse` is likely to
39-
provide a better foundation for library authors *writing* third party
40-
command line argument processing libraries.
14+
.. _choosing-an-argument-parser:
15+
16+
Choosing an argument parsing library
17+
------------------------------------
18+
19+
The standard library includes three argument parsing libraries:
20+
21+
* :mod:`getopt`: a module that closely mirrors the procedural C ``getopt`` API.
22+
Included in the standard library since before the initial Python 1.0 release.
23+
* :mod:`optparse`: a declarative replacement for ``getopt`` that
24+
provides equivalent functionality without requiring each application
25+
to implement its own procedural option parsing logic. First included
26+
in the standard library since the Python 2.3 release.
27+
* :mod:`argparse`: a more opinionated alternative to ``optparse`` that
28+
provides more functionality by default, at the expense of reduced application
29+
flexibility in controlling exactly how arguments are processed. Included in
30+
the standard library since the Python 2.7 and Python 3.2 releases.
31+
32+
In the absence of more specific argument parsing design constraints, :mod:`argparse`
33+
is the recommended choice for implementing command line applications, as it offers
34+
the highest level of baseline functionality with the least application level code.
35+
36+
:mod:`getopt` is retained almost entirely for backwards compatibility reasons.
37+
However, it also serves a niche use case as a tool for prototyping and testing
38+
command line argument handling in ``getopt``-based C applications.
39+
40+
:mod:`optparse` should be considered as an alternative to :mod:`argparse` in the
41+
following cases:
42+
43+
* an application is already using :mod:`optparse` and doesn't want to risk the
44+
subtle behavioural changes that may arise when migrating to :mod:`argparse`
45+
* the application requires additional control over the way options and
46+
positional parameters are interleaved on the command line (including
47+
the ability to disable the interleaving feature completely)
48+
* the application requires additional control over the incremental parsing
49+
of command line elements (while ``argparse`` does support this, the
50+
exact way it works in practice is undesirable for some use cases)
51+
* the application requires additional control over the handling of options
52+
which accept parameter values that may start with ``-`` (such as delegated
53+
options to be passed to invoked subprocesses)
54+
* the application requires some other command line parameter processing
55+
behavior which ``argparse`` does not support, but which can be implemented
56+
in terms of the lower level interface offered by ``optparse``
57+
58+
These considerations also mean that :mod:`optparse` is likely to provide a
59+
better foundation for library authors writing third party command line
60+
argument processing libraries.
61+
62+
As a concrete example, consider the following two command line argument
63+
parsing configurations, the first using ``optparse``, and the second
64+
using ``argparse``:
65+
66+
.. testcode::
67+
68+
import optparse
69+
70+
if __name__ == '__main__':
71+
parser = optparse.OptionParser()
72+
parser.add_option('-o', '--output')
73+
parser.add_option('-v', dest='verbose', action='store_true')
74+
opts, args = parser.parse_args()
75+
process(args, output=opts.output, verbose=opts.verbose)
76+
77+
.. testcode::
78+
79+
import argparse
80+
81+
if __name__ == '__main__':
82+
parser = argparse.ArgumentParser()
83+
parser.add_argument('-o', '--output')
84+
parser.add_argument('-v', dest='verbose', action='store_true')
85+
parser.add_argument('rest', nargs='*')
86+
args = parser.parse_args()
87+
process(args.rest, output=args.output, verbose=args.verbose)
88+
89+
The most obvious difference is that in the ``optparse`` version, the non-option
90+
arguments are processed separately by the application after the option processing
91+
is complete. In the ``argparse`` version, positional arguments are declared and
92+
processed in the same way as the named options.
93+
94+
However, the ``argparse`` version will also handle some parameter combination
95+
differently from the way the ``optparse`` version would handle them.
96+
For example (amongst other differences):
97+
98+
* supplying ``-o -v`` gives ``output="-v"`` and ``verbose=False``
99+
when using ``optparse``, but a usage error with ``argparse``
100+
(complaining that no value has been supplied for ``-o/--output``,
101+
since ``-v`` is interpreted as meaning the verbosity flag)
102+
* similarly, supplying ``-o --`` gives ``output="--"`` and ``args=()``
103+
when using ``optparse``, but a usage error with ``argparse``
104+
(also complaining that no value has been supplied for ``-o/--output``,
105+
since ``--`` is interpreted as terminating the option processing
106+
and treating all remaining values as positional arguments)
107+
* supplying ``-o=foo`` gives ``output="=foo"`` when using ``optparse``,
108+
but gives ``output="foo"`` with ``argparse`` (since ``=`` is special
109+
cased as an alternative separator for option parameter values)
110+
111+
Whether these differing behaviors in the ``argparse`` version are
112+
considered desirable or a problem will depend on the specific command line
113+
application use case.
41114

42115
.. seealso::
43116

@@ -46,10 +119,12 @@
46119
developed as a set of decorated command implementation functions.
47120

48121
Other third party libraries, such as :pypi:`typer` or :pypi:`msgspec-click`,
49-
allow command line interfaces to be specified in ways that effectively
122+
allow command line interfaces to be specified in ways that more effectively
50123
integrate with static checking of Python type annotations.
51124

52-
--------------
125+
126+
Introduction
127+
------------
53128

54129
:mod:`optparse` is a more convenient, flexible, and powerful library for parsing
55130
command-line options than the minimalist :mod:`getopt` module.
@@ -117,10 +192,11 @@ Background
117192
----------
118193

119194
:mod:`optparse` was explicitly designed to encourage the creation of programs
120-
with straightforward, conventional command-line interfaces. To that end, it
121-
supports only the most common command-line syntax and semantics conventionally
122-
used under Unix. If you are unfamiliar with these conventions, read this
123-
section to acquaint yourself with them.
195+
with straightforward command-line interfaces that follow the conventions
196+
established by the :c:func`!getopt` family of functions available to C developers.
197+
To that end, it supports only the most common command-line syntax and semantics
198+
conventionally used under Unix. If you are unfamiliar with these conventions,
199+
reading this section will allow you to acquaint yourself with them.
124200

125201

126202
.. _optparse-terminology:

0 commit comments

Comments
 (0)