-
-
Notifications
You must be signed in to change notification settings - Fork 30.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gh-126180: Remove getopt and optparse deprecation notices #126227
base: main
Are you sure you want to change the base?
Changes from all commits
a560986
0a568f1
55b7215
0971780
09b0237
4cdebde
693a979
50d1ee4
4e50c74
0db2c88
e474e77
43234de
93d7161
bb91b52
7cc72ad
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,11 +13,15 @@ recommended command-line parsing module in the Python standard library. | |
|
||
.. note:: | ||
|
||
There are two other modules that fulfill the same task, namely | ||
:mod:`getopt` (an equivalent for ``getopt()`` from the C | ||
language) and the deprecated :mod:`optparse`. | ||
Note also that :mod:`argparse` is based on :mod:`optparse`, | ||
and therefore very similar in terms of usage. | ||
The standard library includes two other libraries directly related | ||
to command-line parameter processing: the lower level :mod:`optparse` | ||
module (which may require more code to configure for a given application, | ||
but also allows an application to request behaviors that ``argparse`` | ||
doesn't support), and the very low level :mod:`getopt` (which specifically | ||
serves as an equivalent to :c:func:`!getopt` from the C language). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Python |
||
While neither of those modules is covered directly in this guide, many of | ||
the core concepts in ``argparse`` first originated in ``optparse``, so | ||
some aspects of this tutorial will also be relevant to ``optparse`` users. | ||
|
||
|
||
Concepts | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,20 @@ | |
|
||
**Source code:** :source:`Lib/argparse.py` | ||
|
||
.. note:: | ||
|
||
While :mod:`argparse` is the recommended standard library module for | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would not recommend it for now. You can use it on your own risk. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For this PR, I'd like to stick with the status quo as far as recommendations go (that is, only taking the step back from " Taking the extra step to saying " There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indeed. Keep the argparse recommendation. We're not going to dis-recommend the most widely used Python argument parsing library in the world (that causes churn and angst from users). Nor are we going to be adding yet another one to the stdlib in the future. argparse supports most users quite well, "warts" and all, with plenty of popular third party options for yet other behaviors beyond our stdlib options. |
||
*implementing* basic command line applications, authors of third party | ||
command line argument processing libraries may find that the | ||
lower level :mod:`optparse` module serves as a better foundation for | ||
that use case. ``optparse`` (or one of the third party libraries | ||
based on it) may also be worth considering for applications where | ||
``argparse`` doesn't support behaviors that the application requires | ||
(such as entirely disabling support for interspersed options and | ||
positional arguments, or stricter adherence to common Unix and Linux | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd editorialize a little less and elide "stricter" & "common Unix and Linux" and simplify this to "adherence to command line interface concentions related to the handling of values that start with -" |
||
command line interface conventions related to the handling of option | ||
parameter values that start with ``-``). | ||
|
||
-------------- | ||
|
||
.. sidebar:: Tutorial | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
.. _cmdlinelibs: | ||
|
||
******************************** | ||
Command Line Interface Libraries | ||
******************************** | ||
|
||
The modules described in this chapter assist with implementing | ||
command line and terminal interfaces for applications. | ||
|
||
Here's an overview: | ||
|
||
.. toctree:: | ||
:maxdepth: 1 | ||
|
||
argparse.rst | ||
optparse.rst | ||
Comment on lines
+15
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would place There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If anything, this list sure be in purely alphabetical order. passive aggressive opinions via list ordering aren't helpful. 😄 |
||
getpass.rst | ||
fileinput.rst | ||
curses.rst | ||
curses.ascii.rst | ||
curses.panel.rst |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,7 +14,6 @@ in this chapter is: | |
|
||
pathlib.rst | ||
os.path.rst | ||
fileinput.rst | ||
stat.rst | ||
filecmp.rst | ||
tempfile.rst | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,18 +7,13 @@ | |
|
||
**Source code:** :source:`Lib/getopt.py` | ||
|
||
.. deprecated:: 3.13 | ||
The :mod:`getopt` module is :term:`soft deprecated` and will not be | ||
developed further; development will continue with the :mod:`argparse` | ||
module. | ||
|
||
.. note:: | ||
gpshead marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
The :mod:`getopt` module is a parser for command line options whose API is | ||
designed to be familiar to users of the C :c:func:`!getopt` function. Users who | ||
are unfamiliar with the C :c:func:`!getopt` function or who would like to write | ||
less code and get better help and error messages should consider using the | ||
:mod:`argparse` module instead. | ||
This module is considered feature complete. A more object-oriented and | ||
extensible alternative to this API is provided in the :mod:`optparse` | ||
module. Further functional enhancements for command line parameter | ||
processing are provided either as third party modules on PyPI, | ||
or else as features in the :mod:`argparse` module. | ||
|
||
-------------- | ||
|
||
|
@@ -28,6 +23,12 @@ | |
options similar to those supported by GNU software may be used as well via an | ||
optional third argument. | ||
|
||
Users who are unfamiliar with the Unix :c:func:`!getopt` function should consider | ||
using the :mod:`argparse` module instead. Users who are familiar with the Unix | ||
:c:func:`!getopt` function, but would like to get equivalent behavior while | ||
writing less code and getting better help and error messages should consider | ||
using the :mod:`optparse` module. | ||
|
||
This module provides two functions and an | ||
exception: | ||
|
||
|
@@ -144,26 +145,65 @@ | |
output = a | ||
else: | ||
assert False, "unhandled option" | ||
# ... | ||
process(args, output=output, verbose=verbose) | ||
|
||
if __name__ == "__main__": | ||
main() | ||
|
||
Note that an equivalent command line interface could be produced with less code | ||
and more informative help and error messages by using the :mod:`argparse` module:: | ||
and more informative help and error messages by using the :mod:`optparse` module:: | ||
|
||
import argparse | ||
import optparse | ||
|
||
if __name__ == '__main__': | ||
parser = argparse.ArgumentParser() | ||
parser.add_argument('-o', '--output') | ||
parser.add_argument('-v', dest='verbose', action='store_true') | ||
args = parser.parse_args() | ||
# ... do something with args.output ... | ||
# ... do something with args.verbose .. | ||
parser = optparse.OptionParser() | ||
parser.add_option('-o', '--output') | ||
parser.add_option('-v', dest='verbose', action='store_true') | ||
opts, args = parser.parse_args() | ||
process(args, output=opts.output, verbose=opts.verbose) | ||
|
||
A roughly equivalent command line interface for this case can also be | ||
produced by using the :mod:`argparse` module:: | ||
|
||
import argparse | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wrong indentation. Also, add |
||
|
||
if __name__ == '__main__': | ||
parser = argparse.ArgumentParser() | ||
parser.add_argument('-o', '--output') | ||
parser.add_argument('-v', dest='verbose', action='store_true') | ||
parser.add_argument('rest', nargs='*') | ||
args = parser.parse_args() | ||
process(args.rest, output=args.output, verbose=args.verbose) | ||
|
||
However, unlike the ``optparse`` example, this ``argparse`` example will | ||
handle some parameter combinations differently from the way the ``getopt`` | ||
version would handle them. For example (amongst other differences): | ||
|
||
* supplying ``-o -v`` gives ``output="-v"`` and ``verbose=False`` | ||
for both ``getopt`` and ``optparse``, | ||
but a usage error with ``argparse`` | ||
(complaining that no value has been supplied for ``-o/--output``, | ||
since ``-v`` is interpreted as meaning the verbosity flag) | ||
* similarly, supplying ``-o --`` gives ``output="--"`` and ``args=()`` | ||
for both ``getopt`` and ``optparse``, | ||
but a usage error with ``argparse`` | ||
(also complaining that no value has been supplied for ``-o/--output``, | ||
since ``--`` is interpreted as terminating the option processing | ||
and treating all remaining values as positional arguments) | ||
* supplying ``-o=foo`` gives ``output="=foo"`` | ||
for both ``getopt`` and ``optparse``, | ||
but gives ``output="foo"`` with ``argparse`` | ||
(since ``=`` is special cased as an alternative separator for | ||
option parameter values) | ||
|
||
Whether these differing behaviors in the ``argparse`` version are | ||
considered desirable or a problem will depend on the specific command line | ||
application use case. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @serhiy-storchaka ^^^ is the main reason I don't think we should walk back the default argparse recommendation. Many (probably even most) Python devs would consider argparse to be in the right for these 3 examples, and getopt/optparse the ones doing something dubious (even if what they're doing is the common Unix convention). The discrepancies are valid reasons for reverting the soft deprecation (optparse can genuinely be used to define command line behaviours that argparse doesn't support), but it will take less arguable examples than these ones to make the case that optparse should be preferred over argparse in general. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be better to write about these peculiarities in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. agreed. I like that we're giving a list of differences in behavior, but I think it makes more sense to put this in a common section :ref:'d from all three of our command line parsing module docs. I don't expect anyone reading argparse (most likely) or optparse (likely) docs to find this in the getopt docs (presumed least likely to be read). |
||
|
||
.. seealso:: | ||
|
||
Module :mod:`argparse` | ||
Alternative command line option and argument parsing library. | ||
Module :mod:`optparse` | ||
More object-oriented command line option parsing. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO the salient feature of optparse over getopt is that it’s more convenient and automated! «more OO» is not a selling point |
||
|
||
Module :mod:`argparse` | ||
More opinionated command line option and argument parsing library. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,18 +10,53 @@ | |
|
||
**Source code:** :source:`Lib/optparse.py` | ||
|
||
.. deprecated:: 3.2 | ||
The :mod:`optparse` module is :term:`soft deprecated` and will not be | ||
developed further; development will continue with the :mod:`argparse` | ||
module. | ||
.. note:: | ||
|
||
This module is considered feature complete. Further functional enhancements for | ||
command line parameter processing are provided either as third party modules on | ||
PyPI, or else as features in the :mod:`argparse` module. | ||
|
||
.. note:: | ||
|
||
The higher level :mod:`argparse` (rather than this module) is the recommended | ||
standard library module for implementing command line applications unless one | ||
of the following caveats applies: | ||
|
||
* the application requires additional control over the way options and | ||
positional parameters are interleaved on the command line (including | ||
the ability to disable the interleaving feature completely) | ||
* the application requires additional control over the incremental parsing | ||
of command line elements (while ``argparse`` does support this, the | ||
exact way it works in practice is undesirable for some use cases) | ||
* the application requires additional control over the handling of options | ||
which accept parameter values that may start with ``-`` (such as delegated | ||
options to be passed to invoked subprocesses) | ||
* the application requires some other command line parameter processing | ||
behavior which ``argparse`` does not support, but which can be implemented | ||
in terms of the lower level interface offered by ``optparse`` | ||
|
||
These ``argparse`` caveats also mean that :mod:`optparse` is likely to | ||
provide a better foundation for library authors *writing* third party | ||
command line argument processing libraries. | ||
|
||
.. seealso:: | ||
|
||
:pypi:`click` is a third party argument processing library (originally | ||
based on ``optparse``), which allows command line applications to be | ||
developed as a set of decorated command implementation functions. | ||
|
||
Other third party libraries, such as :pypi:`typer` or :pypi:`msgspec-click`, | ||
allow command line interfaces to be specified in ways that effectively | ||
integrate with static checking of Python type annotations. | ||
|
||
-------------- | ||
|
||
:mod:`optparse` is a more convenient, flexible, and powerful library for parsing | ||
command-line options than the old :mod:`getopt` module. :mod:`optparse` uses a | ||
more declarative style of command-line parsing: you create an instance of | ||
:class:`OptionParser`, populate it with options, and parse the command | ||
line. :mod:`optparse` allows users to specify options in the conventional | ||
command-line options than the minimalist :mod:`getopt` module. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replacing |
||
:mod:`optparse` uses a more declarative style of command-line parsing: | ||
you create an instance of :class:`OptionParser`, | ||
populate it with options, and parse the command line. | ||
:mod:`optparse` allows users to specify options in the conventional | ||
GNU/POSIX syntax, and additionally generates usage and help messages for you. | ||
|
||
Here's an example of using :mod:`optparse` in a simple script:: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
:mod:`getopt` and :mod:`optparse` are no longer marked as deprecated. | ||
There are legitimate reasons to use one of these modules in preference to | ||
:mod:`argparse`, and none of these modules are at risk of being removed | ||
from the standard library. Of the three, ``argparse`` remains the | ||
recommended default choice, *unless* one of the concerns noted at the top of | ||
the ``optparse`` module documentation applies. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me try squinting at this from a slightly different angle, feel free to ignore...
:mod:
argparse
was originally created to address some needs that the design of :mod:optparse
made difficult to implement. While initially the majority of the :mod:optparse
interface was imported as a transitional aid, maintaining backwards compatibility was never a goal.