如何使多个选择成为argparse参数中的默认选项,但是一个或多个chocies是可选的?

时间:2017-05-24 13:46:25

标签: python argparse

我想在我的解析器中添加一个参数,其中有多个选项可以从某个参数中选择。但是,默认情况下,我希望默认情况下运行所有​​三个选项,除非用户表明他或她只想运行一个或两个可能的选项。

import argparse

if __name__ == "__main__":
    parser = argparse.ArgumentParser()

    parser.add_argument(
        "-o",
        "--output_type",
        choices= ['count', 'proportion', 'percentage'],
        default= 'count', 'proportion', 'percentage')

    args= parser.parse_args()

    if args.output_type == ['count','proportion','percentage']:
        ###do stuff
    elif args.output_type == 'percentage' or args.output_type == 'count' or args.output_type == 'proportion':
        ###do stuff
    else:
        ###raise error

但它似乎无法正常工作。可能是我的条件树设置不正确,但我不确定。有人可以告诉我如何更好地组织这个吗?

2 个答案:

答案 0 :(得分:2)

如果我按照发布的方式运行你的代码,我会得到一个SyntaxError

  File "stack44160281.py", line 10
    default= 'count', 'proportion', 'percentage')
SyntaxError: non-keyword arg after keyword arg

default= 'count'没问题,但接下来的两个字符串不符合函数的参数规范。

您可能打算将其作为

default= ['count', 'proportion', 'percentage']

但现在我明白了:NameError: name 'args' is not defined你忘记了args = parser.parse_args()行。

最后一行的缩进是错误的。

在纠正所有这些事情(其中任何一项值得close投票)后(并添加诊断print(args)行)。

1436:~/mypy$ python stack44160281.py 
Namespace(output_type=['count', 'proportion', 'percentage'])
do default

1436:~/mypy$ python stack44160281.py -o count
Namespace(output_type='count')
do stuff
1437:~/mypy$ python stack44160281.py -o percentage
Namespace(output_type='percentage')
do stuff
1438:~/mypy$ python stack44160281.py -o wrong
usage: stack44160281.py [-h] [-o {count,proportion,percentage}]
stack44160281.py: error: argument -o/--output_type: invalid choice: 'wrong' (choose from 'count', 'proportion', 'percentage')
1438:~/mypy$ python stack44160281.py -h
usage: stack44160281.py [-h] [-o {count,proportion,percentage}]

optional arguments:
  -h, --help            show this help message and exit
  -o {count,proportion,percentage}, --output_type {count,proportion,percentage}

elif行可以压缩为:

elif args.output_type in ['percentage', 'count', 'proportion']:

几乎所有字符串都可以替换default,例如default='DEFAULT'if args.output_type == 'DEFAULT'它甚至可以保留为默认None,并使用if args.output_type is None:进行测试。

您可以添加其他选项,例如'all',并将其用作default。那会让你的用户提供这个价值。

请注意,choices阻止我们转到else错误行。

事实上,调度可以浓缩为:

if args.output_type in ['percentage', 'count', 'proportion']:
    print('do stuff')
else:
    print('do default')

因为该值保证为choicesdefault之一。

请注意,此设置不是多项选择问题。您的用户仍然只需提供其中一个选项,而不是几个。如果nargsaction发生变化,我们可能会改变这种情况。我们还需要改变测试。

如果output_typenargs='+'参数,则args.output_type将成为列表。您可以使用以下命令测试特定列表:

if args.output_type == ['one', 'two']:

但是如果用户改为给你['two', 'one']该怎么办呢。

通常会使用以下内容对列表进行测试:

for value in args.output_type:
   if value in ['one', 'two']:
        <act>
   else if value in ['three']:
        <act>
   else:
        <act>

如果您想同时测试这两个值,可以使用set,因此订单无关紧要。

有很多组织逻辑的方法。这取决于价值观对您的意义。

答案 1 :(得分:0)

当我尝试运行你的代码时(从我正在使用的python 2.7),它给出了SyntaxError: non-keyword arg after keyword arg。因此,如果您想将所有选项设置为默认值,则可以使用default内置函数,只需设置default = all即可。其次args应在使用之前进行解析,即args = parser.parse_args()

编辑:正如@hpaulj所说,elif args.output_type == 'percentage' or args.output_type == 'count' or args.output_type == 'proportion':可以简化为elif args.output_type in ['percentage', 'count', 'proportion']:

我希望以下可以提供帮助:

import argparse

if __name__ == "__main__":
    parser = argparse.ArgumentParser()

    parser.add_argument(
        "-o",
        "--output_type",
        choices = ['count', 'proportion', 'percentage'],
        default = all)

args = parser.parse_args()

if args.output_type == all:
    print "all"
elif args.output_type in ['percentage', 'count', 'proportion']:
    print "one"
else:
    print "error"