argparse: change argument from positional to optional in certain cases

My script has the following usage:

prog.py login password [--show]

login and password are positional arguments. However, I want to transform them into an optional if another argument ( -s or --show ) is specified. So, the usage will be:

prog.py --show [login] [password]

This is my code:

parser = argparse.ArgumentParser(...)
parser.add_argument('login', help="User login")
parser.add_argument('password', help="User password")
parser.add_argument('-s', '--show', dest='show', action='store_true',
                    help="Show user login and password")

Example:

prog.py login=mylogin password=mypassword

This script saves mylogin and mypassword to the file named authorization.txt

However, prog.py --show should only retrieve information from authorization.txt without requiring login and password arguments and print current user login and password to stdout:

login: mylogin
password: mypassword

I have limited experience with argparse, so pinch of salt required, but here goes...

Positional arguments are always required. If your script does not explicitly require them for everything it needs to do, then, by definition, they are actually optional.

Also, argparse cannot handle changes to the argument structure on a whim. How is it supposed to know what arguments have been passed to it before parser.parse_args() is called?

With that in mind, I reckon add_mutually_exclusive_group() is what you might need https://docs.python.org/2/library/argparse.html#mutual-exclusion

The idea is two create two optional arguments, only one of which can be called at any one time:

prog.py --store [login password] --show

There's no way around these both being optional (yet, that I know of). If you set the required flag to True , argparse will always require one of these arguments to be presented when prog.py is run. So what we're really getting is some sort of quasi-optional-positional argument.

NB You can't add a description / help info to a mutually exclusive group... Bit of a pain.

argparse code:

parser = argparse.ArgumentParser()
exclusive_group = parser.add_mutually_exclusive_group(required=True)
exclusive_group.add_argument('--store', dest='store', nargs=2, type=str,
                                 help="Store user login and password")
exclusive_group.add_argument('--show', dest='show', action='store_true',
                                 help="Show user login and password")
args = parser.parse_args()
print(args)

Running argparse code:

$:python test.py --show
Namespace(show=True, store=None)

$:python test.py --store foo bar
Namespace(show=False, store=['foo', 'bar'])

EDIT: I originally posted that nargs won't allow for an integer value to define the number of variables allowed, but thanks to @hpaulj for correction.

You can use nargs=2 , which means --store must be given 2 arguments and provides an error if it doesn't get 2. The destination store is therefore a list of length 2. This negates any need for any extra code for validation of the number of variables, BUT, this doesn't protect against the ordering of the variables. As these are stored in a list, they could be input in any order... so be careful with that.

链接地址: http://www.djcxy.com/p/28562.html

上一篇: python,在装饰和关闭时感到困惑

下一篇: argparse:在某些情况下将参数从位置更改为可选