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

How to make multiple choices be the default in an argparse argument, but one or more chocies be optional?

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

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

但是好像不能正常使用。可能是我的条件树设置不正确,但我不确定。谁能告诉我如何更好地组织这件事?

当我尝试 运行 您的代码(来自我正在使用的 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"

如果我 运行 你发布的代码我得到一个 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_type 有一个 nargs='+' 参数,那么 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,因此顺序无关紧要。

组织逻辑的方法有很多种。这取决于价值观对你意味着什么。