简体   繁体   中英

Python Argparse: how to make an argument required if and only if one flag is given?

I am wondering how can I make one argument required when one flag is given, and optional when that flag is not given?

import argparse


parser = argparse.ArgumentParser()

parser.add_argument('-c', '--convert', action = 'store_true')
parser.add_argument('-l', '--lookup', action = 'store_true')
parser.add_argument('name', type = str) 

args = parser.parse_args()

if args.name:
    print(args.name)
if args.convert:
    print ("convert now!")

For example, in the codes above, I want name to be required, only when -c is given. When I run the program only with -l , then there is an error:

$ python3 test.py -l
usage: test.py [-h] [-c] [-l] name
test.py: error: the following arguments are required: name

I have tried to use argument group to divide the arguments into two groups 1. -c and name ; 2. -l , but it didn't really work.

Any suggestions are appreciated!

This isn't something argparse can enforce on its own. What you can do is define name to be optional, then check after parsing if your constraint is met.

import argparse


parser = argparse.ArgumentParser()

parser.add_argument('-c', '--convert', action='store_true')
parser.add_argument('-l', '--lookup', action='store_true')
parser.add_argument('name', nargs='?') 

args = parser.parse_args()

# If args.name must be a non-empty string when given,
# you can use 'not args.name' in place of 'args.name is None'
if args.convert and args.name is None:
    parser.error("<name> required with --convert")

if args.name:
    print(args.name)
if args.convert:
    print ("convert now!")

There isn't anything in argparse to do this directly; but it can be approximated in various ways

parser.add_argument('-c', '--convert', action = 'store_true')
parser.add_argument('-l', '--lookup', action = 'store_true')
parser.add_argument('name', nargs='?', default='good default') 

It's not required in either case, but in the case of -c you could either use the good default , or you can complain after parsing.

parser.add_argument('-c', '--convert')
parser.add_argument('-l', '--lookup', nargs='?', default='adefault', const='aconst')

In this case, -c expects an argument, your required name . An argument is optional for -l . If no -l , the value is the default ; if -l without the argument, the value is the const . You could even put -c and -l in a mutually exclusive group.

There isn't a mechanism for requiring several arguments to go together (ie no 'mutually-required-group`). However subparsers work along that line. Do I need to illustrate how subparsers could be use here?

Custom Actions classes can be used to force some sort of interaction between arguments, but usually it's easier to implement that sort of thing after parsing. Remember argparse allows you give arguments in any order. Thus the name positional could occur before -c , or after, or between -l and -c etc.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM