Feel free to skip the "Summary" section at the bottom if you don't want
to read all the details.
This is based on the mostly excellent links provided in Nick ODell's
answer, particular comments in those links, and other comments provided
here (particuarly by hpaulj; hat tip to him).
The Problem
A key design decision in argparse
is that it parses options anywhere
in the command line, i.e., ls somedir/ -l
is just as valid as ls -l somedir/
. (Note that this differs from getopt
, where the non-option
arguments would be ['somedir/', '-l']
in the first example above.)
The end user can apply parsing to only a prefix of a command line by using
the special --
"option," which changes the part of the command line
that's passed to the parser before the parser runs, but clearly
developers wanting to use argparse.REMAINDER
are wanting to avoid making
the user do this.
Unfortunately, it seems that nargs=REMAINDER
doesn't fit well into this
"parse options anywhere in the command line" system. I am not aware of the
exact reasons for this (some of which may be inherent in the logic of what
argparse is trying to do, as opposed to just a matter of doing the
programming); I think that would be a suitable topic for another question.
This started with a bug report "argparse.REMAINDER doesn't work as first
argument" (since moved to GitHub), which could also be
described as a situation where the only argument uses nargs=REMAINDER
.
This brings up a relatively subtle problem for which there's much
discussion, including how nargs=REMAINDER
should work in sub-parsers,
which itself opens up a whole new can of worms.
paulj3's comment goes into much of the detail about the difficulties of
determining REMAINDER
behaviour, determining what its behaviour should
be, and documenting all of this; responses point out that he may not be
correct about certain details. It also points out that the original case
doesn't appear to need or want argparse
:
If you don't want such a gatekeeper [by which he means functionality like
--
—cjs], why [use] argparse at all? Why not use sys.argv[1:] directly?"
The Removal
In the comment above, paulj3 makes a key point:
So some sort of warning about the limitations of REMAINDER would be good.
But the trick is to come up with something that is clear but succinct.
The argparse documentation is already daunting to beginners.
This is generally agreed to be difficult, and nobody seems actually to have
proposed specific changes to the documentation, so paulj3 says in a later
comment:
Since this feature is buggy, and there isn't an easy fix, we should
probably remove any mention of it from the docs. We can still leave it as
an undocumented legacy feature.
There is precedent for leaving nargs constants undocumented.
argparse.PARSER ('+...') is used by the subparser mechanism, but is not
documented. https://bugs.python.org/issue16988
This seemed to attract enough agreement that PRs were submitted and all
mention of REMAINDER
was removed.
The Alternatives
(Note: this is not technically related to the original question here, but I
bring this up mainly because of the common parse_known_args()
confusion
that arises in discussions of nargs=REMAINDER
.)
Nick ODell's answer suggests, based on answers to "python argparse:
unrecognized arguments", that using Parser.parse_known_args()
instead of Parser.parse_args()
is a replacement for nargs=REMAINDER
.
Some answers to the question "Getting the remaining arguments in
argparse" do the same.
These are not correct. The "unrecognised arguments" question is even
dealing with an entirely different problem that nargs=REMANDER
will not
solve. (The actual solution was not to pass sys.argv
to parse_args()
.)
And though there are two mentions of parse_known_args()
in the original
bug report discussion, those are is simply related to demonstrating
argparse
behaviour, and it is never suggested as an alternative.
As for what to do in your particular program, that's heavily dependent on
the program itself and your aims, and would require a separate question
giving a lot more detail about the particular situation. As far as I can
tell, this is just a documentation change, and nargs=REMAINDER
appears
not to be going away, so you could continue to use that. This is discussed
in more detail in several answers to "Getting the remaining arguments in
argparse" (note again that some of those answers incorrectly
suggest parse_known_args()
). This answer gives code for
several solutions to that particular question, and a good warning:
The best all-around answer so far is nargs=REMAINDER
, but it might
really depend on your use case.
Other alternatives include getopt
(which always stops at the first
non-option, avoiding the problem via different and less featureful parsing
logic) and, as suggested above, simply using sys.argv[1:]
if that fits
your situation.
Summary
nargs=REMAINDER
is very hard to document, and may not even fit well
into the design of argparse
, causing complex edge cases. So it appears
that to avoid further complexity in already complex documentation, for an
awkward feature that doesn't fit well with the overall philosophy of how
argparse
parses arguments, it was felt best simply to remove it from the
documentation.
(Whether this was the best way to go is of course a matter of opinion, but
to me, "don't make the documentation more complex" seems a valid argument
to make.)