-
-
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?
gh-126180: Remove getopt and optparse deprecation notices #126227
Conversation
Co-authored-by: Serhiy Storchaka <[email protected]>
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 comment
The reason will be displayed to describe this comment to others. Learn more.
Replacing old
with minimalist
is the only actual wording change here (the rest is just reflowing text)
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.
You are focused on one particular peculiarity in argparse
, but there are many others. The difference is fundamental in the way how optional and positional arguments are parsed.
Doc/howto/argparse.rst
Outdated
@@ -15,7 +15,7 @@ recommended command-line parsing module in the Python standard library. | |||
|
|||
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`. | |||
language) and the lower level :mod:`optparse` module. |
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.
This may create an impression that optparse
is lower level than getopt
.
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.
I'll reorder it to make it clear the "lower level" comparison is relative to argparse
Doc/library/argparse.rst
Outdated
conventions around the handling of option parameter values that start | ||
with ``-`` is desired. |
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.
Not only this. There are other peculiarities that make implementation of compatible interface with argparse
impossible (unlike to getopt
and optparse
).
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.
OK, I had gotten the impression from the Discourse thread that this was the primary quirk, but I can reword these caveats to be less specific to that one issue.
@@ -11,6 +11,18 @@ | |||
|
|||
**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 comment
The 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. optparse
may need more work, but it works as expected. I would recommend it for beginners, which cannot distinguish their own errors from peculiarities of the library.
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.
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 "argparse
is the only non-deprecated argument processing option in the standard library").
Taking the extra step to saying "argparse
is not recommended over optparse
anymore, even for end user applications" would then be a separate follow up question.
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.
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.
argparse.rst | ||
optparse.rst |
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.
I would place optparse
above argparse
.
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.
If anything, this list sure be in purely alphabetical order. passive aggressive opinions via list ordering aren't helpful. 😄
Doc/library/getopt.rst
Outdated
opts, args = parser.parse_args() | ||
process(args, output=opts.output, verbose=opts.verbose) | ||
|
||
An equivalent command line interface for this simple case can also be produced |
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.
Even in this simple example this is not an exact equivalent. For example, -o -v
and -o --
do not work, -o=foo
works differently, you cannot interleave options and positional arguments. I said this is "a roughly equivalent".
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.
I think if we elaborate on the discrepancies here, it may help lay the foundation for weakening the current recommendation to use argparse in a future PR. I'll incorporate more of your notes here tomorrow.
Doc/library/getopt.rst
Outdated
# ... do something with args.output ... | ||
# ... do something with args.verbose .. |
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.
I added this to show the difference in the API between three modules
parser.add_argument('rest', nargs='*')
args = parser.parse_args()
process(args.rest, output=args.output, verbose=args.verbose)
Doc/library/getopt.rst
Outdated
``optparse`` versions due to the way ``argparse`` handles parameter | ||
values that start with ``-``. |
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.
The difference is not only in this.
@serhiy-storchaka I think several of your suggestions are good improvements. I should have time to incorporate them tomorrow (Nov 1 AEST) |
Doc/library/optparse.rst
Outdated
.. seealso:: | ||
|
||
The :pypi:`"click" package <click>` is an ``optparse`` based third party | ||
argument processing library which allows command line applications to be | ||
developed as a set of appropriately decorated command implementation | ||
functions. | ||
|
||
.. seealso:: | ||
|
||
The :pypi:`"Typer" package <click>` is a ``click`` based third party | ||
argument processing library which allows the use of annotated Python | ||
type hints to define an application's command line interface. |
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.
It might make sense to duplicate these seealso
notes in Doc/library/argparse.rst
and Doc/howto/argparse.rst
.
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.
I'm wary of the potential for confusion for folks that are running through "My first command line application" style tutorials, so I'd like to avoid having too much "Should you be using this?" text at the start of the argparse
docs.
Having an off-ramp from argparse
to optparse
and then from there to PyPI alternatives seems like it could be a reasonable middle ground.
@serhiy-storchaka I won't get back to this today, and this weekend isn't looking good either. Early next week will probably be the next update. |
@serhiy-storchaka I ended up procrastinating on my assignment by working on this (amongst other things), so I've pushed some updates for you to take a look at when you're back at work. |
|
||
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 comment
The 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 comment
The reason will be displayed to describe this comment to others. Learn more.
It would be better to write about these peculiarities in the argparse
module documentation. The getopt
module documentation is not the place where users will search information about the argparse
module.
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.
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).
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.
I do not agree with some of these changes, but overall this is a step in the right direction. Let's not drag it in bikeshedding.
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 comment
The reason will be displayed to describe this comment to others. Learn more.
Wrong indentation. Also, add .. testcode::
.
|
||
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 comment
The reason will be displayed to describe this comment to others. Learn more.
It would be better to write about these peculiarities in the argparse
module documentation. The getopt
module documentation is not the place where users will search information about the argparse
module.
``nargs=`` specifiers and better usage messages. When most everything in | ||
:mod:`optparse` had either been copy-pasted over or monkey-patched, it no | ||
longer seemed practical to try to maintain the backwards compatibility. | ||
|
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.
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 comment
The reason will be displayed to describe this comment to others. Learn more.
Python getopt
provides behavior that combines the classic getopt
and the GNU getopt_long
, so the reference (I realize it was there in the original) is incomplete. And to be a little nitpicky, the ISO C standard says nothing about getopt
(POSIX does, but only the single-char getopt
) so From C could be mildly confusing. Maybe something like: (which specifically serves as an equivalent to the getopt family of functions familiar to C language programmers)?
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 comment
The 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 -"
@@ -11,6 +11,18 @@ | |||
|
|||
**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 comment
The 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.
argparse.rst | ||
optparse.rst |
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.
If anything, this list sure be in purely alphabetical order. passive aggressive opinions via list ordering aren't helpful. 😄
|
||
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 comment
The 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).
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 comment
The 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
getopt and optparse are in no way at risk of being removed,
as they have genuinely valid use cases. Those use cases
(mimicing the C getopt API, implementing third party
command line argument processing libraries) are just
far less common than the ones that argparse addresses.
Relevant issue is #126180.
📚 Documentation preview 📚: https://cpython-previews--126227.org.readthedocs.build/