关于python:Argparse:“可选参数”下列出的必需参数?

Argparse: Required arguments listed under “optional arguments”?

我使用下面的简单代码来解析一些参数;请注意,其中一个参数是必需的。不幸的是,当用户在不提供参数的情况下运行脚本时,显示的用法/帮助文本并不表示存在一个非可选参数,我觉得这非常令人困惑。如何让python指示参数不是可选的?

代码如下:

1
2
3
4
5
6
7
8
9
import argparse
if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description='Foo')
    parser.add_argument('-i','--input', help='Input file name', required=True)
    parser.add_argument('-o','--output', help='Output file name', default="stdout")
    args = parser.parse_args()
    print ("Input file: %s" % args.input )
    print ("Output file: %s" % args.output )

当在不提供必需参数的情况下运行上述代码时,我得到以下输出:

1
2
3
4
5
6
7
8
9
10
usage: foo.py [-h] -i INPUT [-o OUTPUT]

Foo

optional arguments:
    -h, --help            show this help message and exit
    -i INPUT, --input INPUT
                          Input file name
    -o OUTPUT, --output OUTPUT
                          Output file name


---开头的参数通常被认为是可选的。所有其他参数都是位置参数,设计也同样需要(如位置函数参数)。可能需要可选的参数,但这有点违背它们的设计。因为它们仍然是非位置参数的一部分,所以即使它们是必需的,它们仍将列在令人困惑的标题"可选参数"下。然而,使用部分中缺少的方括号表明它们确实是必需的。

另请参见文档:

In general, the argparse module assumes that flags like -f and --bar indicate optional arguments, which can always be omitted at the command line.

Note: Required options are generally considered bad form because users expect options to be optional, and thus they should be avoided when possible.

也就是说,帮助中的头"位置参数"和"可选参数"是由两个参数组生成的,在两个参数组中,参数被自动分隔为两个参数组。现在,您可以"侵入其中"并更改可选参数的名称,但是一个更优雅的解决方案是为"所需命名参数"(或您想调用的参数)创建另一个组:

1
2
3
4
5
parser = argparse.ArgumentParser(description='Foo')
parser.add_argument('-o', '--output', help='Output file name', default='stdout')
requiredNamed = parser.add_argument_group('required named arguments')
requiredNamed.add_argument('-i', '--input', help='Input file name', required=True)
parser.parse_args(['-h'])
1
2
3
4
5
6
7
8
9
10
11
12
usage: [-h] [-o OUTPUT] -i INPUT

Foo

optional arguments:
  -h, --help            show this help message and exit
  -o OUTPUT, --output OUTPUT
                        Output file name

required named arguments:
  -i INPUT, --input INPUT
                        Input file name


由于我喜欢在可选之前列出所需的参数,因此我通过以下方式绕过它:

1
2
3
4
5
6
7
    parser = argparse.ArgumentParser()
    parser._action_groups.pop()
    required = parser.add_argument_group('required arguments')
    optional = parser.add_argument_group('optional arguments')
    required.add_argument('--required_arg')
    optional.add_argument('--optional_arg')
    return parser.parse_args()

这个结果是:

1
2
3
4
5
6
7
8
usage: main.py [-h] [--required_arg REQUIRED_ARG]
               [--optional_arg OPTIONAL_ARG]

required arguments:
  --required_arg REQUIRED_ARG

optional arguments:
  --optional_arg OPTIONAL_ARG

我可以在没有"帮助"出现在可选参数组中的情况下生活。


建在@Karl Rosaen

1
2
3
4
5
6
7
8
parser = argparse.ArgumentParser()
optional = parser._action_groups.pop() # Edited this line
required = parser.add_argument_group('required arguments')
# remove this line: optional = parser...
required.add_argument('--required_arg')
optional.add_argument('--optional_arg')
parser._action_groups.append(optional) # added this line
return parser.parse_args()

这个结果是:

1
2
3
4
5
6
7
8
9
usage: main.py [-h] [--required_arg REQUIRED_ARG]
           [--optional_arg OPTIONAL_ARG]

required arguments:
  --required_arg REQUIRED_ARG

optional arguments:
  -h, --help                    show this help message and exit
  --optional_arg OPTIONAL_ARG