Add PEP 389: argparse - new command line parsing module.

This commit is contained in:
Brett Cannon 2009-09-27 19:42:40 +00:00
parent 989165fe9e
commit 562039f287
1 changed files with 224 additions and 0 deletions

224
pep-0389.txt Normal file
View File

@ -0,0 +1,224 @@
PEP: 389
Title: argparse - new command line parsing module
Version: $Revision$
Last-Modified: $Date$
Author: Steven Bethard <steven.bethard@gmail.com>
Status: Draft
Type: Standards Track
Content-Type: text/x-rst
Created: 25-Sep-2009
Python-Version: 2.7 and 3.2
Post-History:
Abstract
========
This PEP proposes inclusion of the argparse [1]_ module in the Python
standard library in Python 2.7 and 3.2.
Motivation
==========
The argparse module is a command line parsing library which provides
more functionality than the existing command line parsing modules in
the standard library, getopt [2]_ and optparse [3]_. It includes
support for positional arguments (not just options), subcommands,
required options, options syntaxes like "/f" and "+rgb", zero-or-more
and one-or-more style arguments, and many other features the other
two lack.
The argparse module is also already a popular third-party replacement
for these modules. It is used in projects like IPython (the Scipy
Python shell) [4]_, is included in Debian testing and unstable [5]_,
and since 2007 has had various requests for its inclusion in the
standard library [6]_ [7]_ [8]_. This popularity suggests it may be
a valuable addition to the Python libraries.
Why aren't getopt and optparse enough?
======================================
One argument against adding argparse is that thare are "already two
different option parsing modules in the standard library" [9]_. The
following is a list of features provided by argparse but not present
in getopt or optparse:
* While it is true there are two *option* parsing libraries, there
are no full command line parsing libraries -- both getopt and
optparse support only options and have no support for positional
arguments. The argparse module handles both, and as a result, is
able to generate better help messages, avoiding redundancies like
the ``usage=`` string usually required by optparse.
* The argparse module values practicality over purity. Thus, argparse
allows required options and customization of which characters are
used to identify options, while optparse explicitly states "the
phrase 'required option' is self-contradictory" and that the option
syntaxes ``-pf``, ``-file``, ``+f``, ``+rgb``, ``/f`` and ``/file``
"are not supported by optparse, and they never will be".
* The argparse module allows options to accept a variable number of
arguments using ``nargs='?'``, ``nargs='*'`` or ``nargs='+'``. The
optparse module provides an untested recipe for some part of this
functionality [10]_ but admits that "things get hairy when you want
an option to take a variable number of arguments."
* The argparse module supports subcommands, where a main command
line parser dispatches to other command line parsers depending on
the command line arguments. This is a common pattern in command
line interfaces, e.g. ``svn co`` and ``svn up``.
Why isn't the functionality just being added to optparse?
=========================================================
Clearly all the above features offer improvements over what is
available through optparse. A reasonable question then is why these
features are not simply provided as patches to optparse, instead of
introducing an entirely new module. In fact, the original development
of argparse intended to do just that, but because of various fairly
constraining design decisions of optparse, this wasn't really
possible. Some of the problems included:
* The optparse module exposes the internals of its parsing algorithm.
In particular, ``parser.largs`` and ``parser.rargs`` are guaranteed
to be available to callbacks [11]_. This makes it extremely
difficult to improve the parsing algorithm as was necessary in
argparse for proper handling of positional arguments and variable
length arguments. For example, ``nargs='+'`` in argparse is matched
using regular expressions and thus has no notion of things like
``parser.largs``.
* The optparse extension APIs are extremely complex. For example,
just to use a simple custom string-to-object conversion function,
you have to subclass ``Option``, hack class attributes, and then
specify your custom option type to the parser, like this::
class MyOption(Option):
TYPES = Option.TYPES + ("mytype",)
TYPE_CHECKER = copy(Option.TYPE_CHECKER)
TYPE_CHECKER["mytype"] = check_mytype
parser = optparse.OptionParser(option_class=MyOption)
parser.add_option("-m", type="mytype")
For comparison, argparse simply allows conversion functions to be
used as ``type=`` arguments directly, e.g.::
parser = argparse.ArgumentParser()
parser.add_option("-m", type=check_mytype)
But given the baroque customization APIs of optparse, it is unclear
how such a feature should interact with those APIs, and it is
quite possible that introducing the simple argparse API would break
existing custom Option code.
* Both optparse and argparse parse command line arguments and assign
them as attributes to an object returned by ``parse_args``.
However, the optparse module guarantees that the ``take_action``
method of custom actions will always be passed a ``values`` object
which provides an ``ensure_value`` method [12]_, while the argparse
module allows attributes to be assigned to any object, e.g.::
foo_object = ...
parser.parse_args(namespace=foo_object)
foo_object.some_attribute_parsed_from_command_line
Modifying optparse to allow any object to be passed in would be
difficult because simply passing the ``foo_object`` around instead
of a ``Values`` instance will break existing custom actions that
depend on the ``ensure_value`` method.
Because of issues like these, which made it unreasonably difficult
for argparse to stay compatible with the optparse APIs, argparse was
developed as an independent module. Given these issues, merging all
the argparse features into optparse with no backwards
incompatibilities seems unlikely.
Deprecation of getopt and optparse
==================================
There is still some debate over the best way (if at all) to encourage
users to move from getopt and optparse to their replacement,
argparse. The current recommendation of this PEP is the following
conservative deprecation strategy:
* Python 3.2, Python 2.7 and any later Python 2.X releases --
PendingDeprecation warnings, which by default are not displayed,
and documentation notes directing users of getopt and optparse to
argparse.
* Python 3.3 -- Same as above
* Python 3.4 -- Deprecation warnings for getopt and optparse, which
by default *are* displayed.
Though this is slower than the usual deprecation process, it seems
prudent to avoid producing any casually visible Deprecation warnings
until Python 3.X has had some additional time to attract developers.
Open Issues
===========
The argparse module supports Python from 2.3 up through 3.2 and as a
result relies on traditional ``%(foo)s`` style string formatting. It
has been suggested that it might be better to use the new style
``{foo}`` string formatting [13]_. This seems like a good idea, but
would break backwards compatibility for existing argparse-based
scripts unless we can come up with a way to reasonably support both
syntaxes.
References
==========
.. [1] argparse
(http://code.google.com/p/argparse/)
.. [2] getopt
(http://docs.python.org/library/getopt.html)
.. [3] optparse
(http://docs.python.org/library/optparse.html)
.. [4] argparse in IPython
(http://mail.scipy.org/pipermail/ipython-dev/2009-April/005102.html)
.. [5] argparse in Debian
(http://packages.debian.org/search?keywords=python-argparse)
.. [6] 2007-01-03 request for argparse in the standard library
(http://mail.python.org/pipermail/python-list/2007-January/592646.html)
.. [7] 2009-06-09 request for argparse in the standard library
(http://bugs.python.org/issue6247)
.. [8] 2009-09-10 request for argparse in the standard library
(http://mail.python.org/pipermail/stdlib-sig/2009-September/000342.html)
.. [9] Fredrik Lundh response to [6]_
(http://mail.python.org/pipermail/python-list/2007-January/592675.html)
.. [10] optparse variable args
(http://docs.python.org/library/optparse.html#callback-example-6-variable-arguments)
.. [11] parser.largs and parser.rargs
(http://docs.python.org/library/optparse.html#how-callbacks-are-called)
.. [12] take_action values argument
(http://docs.python.org/library/optparse.html#adding-new-actions)
.. [13] use {}-formatting instead of %-formatting
(http://bugs.python.org/msg89279)
Copyright
=========
This document has been placed in the public domain.
..
Local Variables:
mode: indented-text
indent-tabs-mode: nil
sentence-end-double-space: t
fill-column: 70
coding: utf-8
End: