9

I want to create an optional argument, which will be the '-- ' (double dash and a space) and get everything after it as its value. The problem is that some other optional arguments might appear after '-- '. I don't want these to be parsed as optional arguments, but as the values of '-- '. For example:

python prog1 --foo 1 --bar 2

Here foo and bar are optional arguments with values 1 and 2 respectively

python prog1 --foo 1 --bar 2 -- --foo 4 --bar 14

Here I want foo and bar that come before '-- ' to be parsed as optional arguments. But I want '--foo 4 --bar 14' to be parsed as the value of the optional argument '-- '. I would like to do this without renaming the parameters that come after '-- ' to foo2 and bar2, if possible.

So is this possible? And how could this be implemented?

5
  • 1
    Why do you want to do this? It's a complete antipattern, and will likely just confuse people (/ your future self). Commented Sep 16, 2014 at 15:19
  • 10
    @will -- This isn't a complete anti-pattern. This is actually a relatively common way to specify arguments that will be passed to a slave program (maybe via subprocess.Popen). Commented Sep 16, 2014 at 15:21
  • @mgilson So i just read about this. That's news to me. Commented Sep 16, 2014 at 15:25
  • 2
    In fact, argparse already supports the common convention of using -- to signal the end of option parsing. Commented Sep 16, 2014 at 15:41
  • -- is commonly used on Unix-like OSes to separate arguments from raw input (often the raw input represents the arguments to be passed to some other command, as in the case of xargs). See unix.stackexchange.com/q/11376/4322. Commented Feb 10, 2017 at 13:29

2 Answers 2

17

argparse already supports -- as an end-of-options terminator. The only difference is that the default handling treats the following arguments individually. Suppose prog1 simply looks like

import argparse

p = argparse.ArgumentParser()

p.add_argument('--foo')
p.add_argument('--bar')
p.add_argument('remaining', nargs=argparse.REMAINDER)

print p.parse_args()

Then the command

% python prog1 --foo 1 --bar 2 -- --foo 4 --bar 14

produces

Namespace(bar='2', foo='1', remaining=['--', '--foo', '4', '--bar', '14'])

(rather than Namespace(..., remaining='-- --foo 4 --bar 14')). Than can be fixed with a quick post-processing step, if necessary:

args = p.parse_args()
args.remaining = " ".join(args.remaining)
print args

Then the result is

Namespace(bar='2', foo='1', remaining='-- --foo 4 --bar 14')

Discarding the -- argument requires some additional post-processing:

args = p.parse_args()
if args.remaining[0] == "--":
    args = args[1:]
Sign up to request clarification or add additional context in comments.

6 Comments

This is brilliant -- however, I can't seem to find it in the docs. The closest that I have been able to find is argparse.REMAINDER, but that doesn't seem to use the -- separator...
See the very end of section 15.4.4.3 (link to the Python 2.7 version of the documentation).
Thanks for reminding me about REMAINDER; that seems like a better choice than * (at least more descriptive; I can't tell if there is a functional difference in this case.)
Nice. Well, you have my +1 anyway -- and I learned something new.
I ran this code and my remaining was remaining=['--', '--foo', '4', '--bar', '14']. Note the -- showed up in the remaining.
|
1

It looks like the docopt library can do this for you;

From the usage-pattern-format section:

"[--]". Double dash "--" is used by convention to separate positional arguments that can be mistaken for options. In order to support this convention add "[--]" to your usage patterns.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.