argparse参数依赖 [英] argparse argument dependency

查看:118
本文介绍了argparse参数依赖的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我使用以下选项调用以下脚本:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆