argparse参数依赖 [英] argparse argument dependency
问题描述
如果我使用以下选项调用以下脚本:
If I call the script below with these options:
--user u1 --password p1 --foo f1 --user u2 --user u3 --password p3
然后它将打印:
Namespace(foo=['bar', 'f1'], password=['p1', 'p3'], user=['u1', 'u2', 'u3'])
问题:我有什么办法可以在用户和密码之间建立依赖关系,因为未指定用户u2的密码,所以会引发错误?
Question: Is there any way for me to set up a dependency between user and password, so it throws an error, because password for user u2 is not specified?
缺少相关问题:如何为所有用户指定默认的foo值?使用给定的输入,我希望foo等于['f1','bar','bar'].
Less relevant question: How do I specify a default foo value for all users? With the given input I would like foo to equal ['f1','bar','bar'].
一个主要问题的解决方案是检查列表用户和密码的长度是否相同,但这与我要查找的内容不完全相同.
A solution for my main question would be to check that the lists user and password have the same length, but it's not quite what I'm looking for.
这是脚本:
import argparse
parser = argparse.ArgumentParser()
group = parser.add_argument_group('authentication')
group.add_argument('--user', action='append', required=True)
group.add_argument('--password', action='append', required=True)
group.add_argument('--foo', action='append', default=['bar'])
print(parser.parse_args())
推荐答案
在您的情况下,由于必须始终一起指定选项,或者都不指定选项,因此可以使用以下两个参数将它们连接到唯一的--user-and-password
选项中: nargs=2
.这样可以大大简化值的处理.
In your case, since the options must always be specified together, or none of them, you could join them into a unique --user-and-password
option with two arguments using nargs=2
. This would simplify a lot the handling of the values.
实际上,您希望能够提供多个对,但是找到第一个选项时,required=True
就可以满足要求,因此对于检查设置中的所需内容几乎没有用.
In fact you want to be able to provide multiple pairs, but required=True
is satisfied when the first option is found, so it's pretty much useless for checking what you want in your setting.
执行此操作的另一种方法是使用自定义操作.例如:
The other way to do this is to use a custom action. For example:
import argparse
class UserAction(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
if len(namespace.passwords) < len(namespace.users):
parser.error('Missing password')
else:
namespace.users.append(values)
class PasswordAction(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
if len(namespace.users) <= len(namespace.passwords):
parser.error('Missing user')
else:
namespace.passwords.append(values)
parser = argparse.ArgumentParser()
parser.add_argument('--password', dest='passwords', default=[], action=PasswordAction, required=True)
parser.add_argument('--user', dest='users', default=[], action=UserAction, required=True)
print(parser.parse_args())
用作:
$python3 ./test_argparse.py --user 1 --password 2 --password 2 --user 3 --password 3
usage: test_argparse.py [-h] --password PASSWORDS --user USERS
test_argparse.py: error: Missing user
并且:
$python3 ./test_argparse.py --user 1 --password 2 --user 2 --user 3 --password 3
usage: test_argparse.py [-h] --password PASSWORDS --user USERS
test_argparse.py: error: Missing password
(请注意,此解决方案要求--user
在--password
之前,否则列表的长度不能提供足够的信息来了解缺少选项时的情况.)
(Note that this solution requires --user
to come before --password
, otherwise the lengths of the lists don't provide enough information to understand when an option is missing.)
最后一个解决方案是只使用action='append'
并在最后测试值列表.但是,这将允许像--user A --user B --password A --password B
这样的东西,您可能想允许也可能不是.
The last solution would be to simply use action='append'
and test at the end the lists of values. However this would allow things like --user A --user B --password A --password B
which may or may not be something you want to allow.
这篇关于argparse参数依赖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!