5

I am trying to implement an command line argument with argparse in a way that only none or once is accepted. Multiple occurences should be rejected.

I use the following code

#!/usr/bin/env python3
import argparse
cmd_parser = argparse.ArgumentParser()
cmd_parser.add_argument('-o', dest='outfile')
cmd_line = cmd_parser.parse_args()
print(cmd_line.outfile)

One argument gives the expected result:

./test.py -o file1
file1

When issuing the argument twice, the first occurence is silently ignored:

./test.py -o file1 -o file2
file2

I also tried nargs=1 and action='store' without reaching the desired result.

How can I tell argparse to reject multiple argument occurances?

sd2k9
  • 53
  • 3
  • A more recent answer, https://stackoverflow.com/questions/68170827/how-do-i-tell-argparse-to-allow-an-argument-only-once, suggests using the 'append' action. – hpaulj Jun 29 '21 at 02:20
  • Does this answer your question? [argparse - disable same argument occurrences](https://stackoverflow.com/questions/23032514/argparse-disable-same-argument-occurrences) – anthonyryan1 Mar 16 '23 at 15:55

1 Answers1

7

It could be arranged with a custom Action:

import argparse

class Once(argparse.Action):
    def __init__(self, *args, **kwargs):
        super(Once, self).__init__(*args, **kwargs)
        self._count = 0

    def __call__(self, parser, namespace, values, option_string=None):
        # print('{n} {v} {o}'.format(n=namespace, v=values, o=option_string))
        if self._count != 0:
            msg = '{o} can only be specified once'.format(o=option_string)
            raise argparse.ArgumentError(None, msg)
        self._count = 1
        setattr(namespace, self.dest, values)

cmd_parser = argparse.ArgumentParser()
cmd_parser.add_argument('-o', dest='outfile', action=Once, default='/tmp/out')
cmd_line = cmd_parser.parse_args()
print(cmd_line.outfile)

You can specify a default:

% script.py 
/tmp/out

You can specify -o once:

% script.py -o file1 
file1

But specifying -o twice raises an error:

% script.py -o file1 -o file2
usage: script.py [-h] [-o OUTFILE]
script.py: error: -o can only be specified once
unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • Thank you - works as expected. I was looking for a solution within argparse, thats why I did overlooked the custom Action approach. – sd2k9 Feb 17 '13 at 14:46
  • I would add to the check the default value, `if getattr(namespace, self.dest) is not None and self.default is None:` because if you specify a default value it would fail, and not because the argument is repeated. – lasote Nov 02 '17 at 08:25
  • @lasote: I think using that condition would allow `-o` to be specified more than once without raising an error since `self.default` will not be `None` if you specify a non-None default value. I've changed the code above to accommodate a default value in a different way above. – unutbu Nov 02 '17 at 11:59