This question already has an answer here:
-
Can't get argparse to read quoted string with dashes in it?
4 answers
I'd like to pass an "argument" to argument.
I.e., in the following code:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-a")
print parser.parse_args(['-a', 'hi'])
print parser.parse_args(['-a', '-hi'])
The output is:
Namespace(a='hi')
usage: problem.py [-h] [-a A]
problem.py: error: argument -a: expected one argument
While I'd like it to be:
Namespace(a='hi')
Namespace(a='-hi')
How can I achieve that?
I've seen in the help the section 15.4.4.3. Arguments containing -
, but it seems to support only negative numbers. Also, they suggest passing "--", but it's not good in my use case, but everything after the "--" isn't treated as argument (if I understand correctly).
But I want "-a" to consume only 1 argument, and then continue parsing the other arguments as real arguments.
How can it be done?
EDIT
Adding a space before the argument works:
print parser.parse_args(['-a', ' -hi'])
But is there a way to achieve that, without requiring the user to add spaces?
Here's a parser subclass that implements the latest suggestion on the https://bugs.python.org/issue9334. Feel free to test it.
class ArgumentParserOpt(ArgumentParser):
def _match_argument(self, action, arg_strings_pattern):
# match the pattern for this action to the arg strings
nargs_pattern = self._get_nargs_pattern(action)
match = _re.match(nargs_pattern, arg_strings_pattern)
# if no match, see if we can emulate optparse and return the
# required number of arguments regardless of their values
#
if match is None:
import numbers
nargs = action.nargs if action.nargs is not None else 1
if isinstance(nargs, numbers.Number) and len(arg_strings_pattern) >= nargs:
return nargs
# raise an exception if we weren't able to find a match
if match is None:
nargs_errors = {
None: _('expected one argument'),
OPTIONAL: _('expected at most one argument'),
ONE_OR_MORE: _('expected at least one argument'),
}
default = ngettext('expected %s argument',
'expected %s arguments',
action.nargs) % action.nargs
msg = nargs_errors.get(action.nargs, default)
raise ArgumentError(action, msg)
# return the number of arguments matched
return len(match.group(1))
It replaces one method providing a fall back option when the regular argument matching fails.
If you and your users can live with it, the long flag fix is best --arg=-a
is simplest. This unambiguously specifies -a
as an argument to the --arg
Action.