问题
The program has 2 arguments to deal with: state and key. I need to have a possibility to give as input the following options:
- prog -state state_value
- prog -key key_value
- prog -state state_value -key key_value
The closest thing is using mutually excluding groups, but it unables the possibility to give both arguments as input at once.
回答1:
I think this is beyond the abilities of argparse. You could perform a simple validation on the returned namespace afterwards though. You should include in your help that at least once of state or key is required.
def validate(namespace, parser):
if not any(arg in {"state", "key"} for arg in vars(namespace).keys()):
parser.print_help()
parser.exit(2)
namespace = parser.parse_args()
validate(namespace, parser)
回答2:
As noted in https://stackoverflow.com/a/24911007/901925 there isn't a built in mechanism for testing this, but it is easy to make such a test after parsing. Assuming the arguments have the default default
of None
, such a test could be:
if args.state is None and args.key is None:
parser.error('At least one of the arguments is required ')
Eventually argparse
might have such a mechanism. There is a bug request for more testing power in groups, http://bugs.python.org/issue11588
One idea is to add UsageGroups, modeled on mutually exclusive groups, but with more general logic. The code isn't available for download, but I'd be interested in hearing whether this example is clear.
parser = argparse.ArgumentParser(prog='prog')
group = parser.add_usage_group(kind='any', required=True)
group.add_argument('-s', '--state', metavar='state_value')
group.add_argument('-k', '--key', metavar='key_value')
args = parser.parse_args()
print(args)
with an error message:
usage: prog [-h] (-s state_value | -k key_value)
prog: error: group any(): some of the arguments [state, key] is required
An alternative in the usage line is (-s state_value, -k key_value)
, since |
is already being used for the mutually exclusive xor
relation. The usage
and error message could be customized.
回答3:
#!/usr/bin/python
#-*- coding:utf-8 -*-
import sys
paras = sys.argv.pop(0)
state_value = None
key_value = None
i=0
while i < len(paras):
if paras[i] == '-state':
state_value = paras[i]
elif paras[i] == '-key':
key_value = paras[i]
i += 2
if state_value:
# do something
pass
if key_value:
# do something
pass
来源:https://stackoverflow.com/questions/24906478/how-to-make-at-least-one-argument-required-and-have-the-possibility-to-take-all