4
usage:  [-h] [--foo FOO] bar
  1. How do I make sure that default value of FOO is abc if I execute my script like below

./myscript.py --foo bar --> bar is positional argument here. but args.foo is considering bar as argument of '--foo'. I want args.foo to be abc and bar to be the positional argument

2 Answers 2

4

You can't, not without reworking your arguments.

You should use two switches here; one to switch on the behaviour, and one to override the default value picked. You can make the second switch imply the first:

usage: [-h] [--foo] [--foo-setting FOO] bar

where --foo is a boolean switch that toggles the behaviour, and --foo-setting lets you set the configuration for the switch:

parser.add_argument('--foo', action='store_true')
parser.add_argument('--foo-setting', help='Set the value for foo, implies --foo is given')

# ...
args = parser.parse_args()

if args.foo_setting is not None:
    # default was overridden, explicitly enable the foo feature
    args.foo = True

if args.foo:
    foo_feature_setting = args.foo_setting or 'default value'
Sign up to request clarification or add additional context in comments.

2 Comments

The problem is, I want to add to mutual exclusive group. Is it possible to have multiple option in one set of the group?
@tez: no; but you are free to add additional tests after parsing. If foo_setting was set but another mutually exclusive group option was picked, then that's an error you need to manually detect.
1

Have you tried using -- to separate the --foo argument(s) from the bar?


With this basic setup:

p=argparse.ArgumentParser()
p.add_argument('--foo',nargs='?',const='abc', default='other')
p.add_argument('bar')

In [633]: p.parse_args(['bar'])
Out[633]: Namespace(bar='bar', foo='other')

In [634]: p.parse_args(['bar','--foo'])
Out[634]: Namespace(bar='bar', foo='abc')

In [635]: p.parse_args(['bar','--foo','test'])
Out[635]: Namespace(bar='bar', foo='test')

In [636]: p.parse_args(['--foo','bar'])
usage: ipython3 [-h] [--foo [FOO]] bar
'error message'

The plain --foo can occur AFTER bar. 'other' ('default) is the value it gets if absent, 'abc' (theconst`) the value it gets if present but 'empty'.

But as you found out, when --foo is first it consumes the following string, leaving nothing for the positional argument. In other words, when handling --foo, it does not take into account the future needs of bar.

If I add another argument

p.add_argument('--baz',action='store_true')
p.parse_args(['--foo','--baz','bar'])
# Namespace(bar='bar', baz=True, foo='abc')

This works because --baz marks the end of --foo arguments.

You can also use -- to mark the end of optionals and the start of postionals:

p.parse_args(['--foo','--','bar'])

There is a bug issue that tries to rectify this by reserving strings for trailing positionals http://bugs.python.org/issue9338 argparse optionals with nargs='?', '*' or '+' can't be followed by positionals

But the patch is not trivial. -- is your best tool at this time.

I don't follow your comment to Martijn about mutually exclusive group(s).

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.