必需参数列在“可选参数”下?

我使用下面的简单代码来解析一些参数;注意,其中一个是必需的。不幸的是,当用户在不提供参数的情况下运行脚本时,显示的usage/help文本并没有表明存在一个非可选参数,这让我感到非常困惑。我怎样才能让python指出一个参数不是可选的?

代码如下:

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 )

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

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
291167 次浏览

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

另见文档:

一般来说,argparse模块假定-f和——bar之类的标志表示可选参数,在命令行中总是可以省略这些参数。

必选选项通常被认为是糟糕的形式,因为用户希望选项是可选的,因此应该尽可能避免它们。

也就是说,帮助中的头“位置参数”“可选参数”是由两个参数组生成的,参数被自动分离到其中。现在,你可以“侵入”它并更改可选参数的名称,但更优雅的解决方案是为“必选命名参数”(或任何你想叫它们的名字)创建另一个组:

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'])
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

因为我更喜欢在可选参数之前列出必选参数,我通过以下方法来解决它:

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', required=True)
optional.add_argument('--optional_arg')
return parser.parse_args()

这输出:

usage: main.py [-h] --required_arg REQUIRED_ARG [--optional_arg OPTIONAL_ARG]


required arguments:
--required_arg REQUIRED_ARG


optional arguments:
--optional_arg OPTIONAL_ARG

我可以没有-h, --help出现在可选参数组中。

以@Karl Rosaen为基础

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', required=True)
optional.add_argument('--optional_arg')
parser._action_groups.append(optional) # added this line
return parser.parse_args()

这输出:

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

再一次,以@RalphyZ为基础

这个不会破坏暴露的API。

from argparse import ArgumentParser, SUPPRESS
# Disable default help
parser = ArgumentParser(add_help=False)
required = parser.add_argument_group('required arguments')
optional = parser.add_argument_group('optional arguments')


# Add back help
optional.add_argument(
'-h',
'--help',
action='help',
default=SUPPRESS,
help='show this help message and exit'
)
required.add_argument('--required_arg', required=True)
optional.add_argument('--optional_arg')

它将显示与上面相同的内容,并且应该在未来的版本中存在:

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

您不需要重写可选组。

只做:

parser = argparse.ArgumentParser()
required = parser.add_argument_group('required arguments')
required.add_argument('--required_arg', required=True)
# All arguments set via parser directly will automatically go to the optional group
parser.add_argument('--optional_arg')
parser.print_help()

会打印出来

usage: [-h] --required_arg REQUIRED_ARG [--optional_arg OPTIONAL_ARG]


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


required arguments:
--required_arg REQUIRED_ARG

如果您希望在可选参数之前有必要的参数,您可以执行以下操作:

parser = argparse.ArgumentParser()
optional = parser._action_groups.pop()
required = parser.add_argument_group('required arguments')
parser._action_groups.append(optional)
required.add_argument('--required_arg', required=True)
optional.add_argument('--optional_arg')
parser.print_help()

它将以正确的顺序打印组:

usage: [-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

注意:根据Christophe Vu-Brugier的说法,下面的代码从Python 3.10版本开始就不能工作了。

默认有2个参数组在解析器中。_action_groups:位置参数和命名参数(标题为“可选参数”)。 您可以将命名的可选参数添加到现有的“可选参数”组中,并将必需的命名参数添加到新的“必选参数”组中。之后,您可以重新排序组:

import argparse


parser = argparse.ArgumentParser(description='Foo')


required = parser.add_argument_group('required arguments')


required.add_argument('-i','--input', help='Input file name', required=True)
parser.add_argument('-o','--output', help='Output file name', default="stdout")


groups_order = {
'positional arguments': 0,
'required arguments': 1,
'optional arguments': 2
}
parser._action_groups.sort(key=lambda g: groups_order[g.title])


parser.parse_args(['-h'])

输出:

usage: argparse_argument_groups.py [-h] -i INPUT [-o OUTPUT]


Foo


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


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

必需的参数通常是“位置的”;使用argparse时的参数。

    parser = argparse.ArgumentParser(description="Foo")
parser.add_argument("username")
parser.add_argument("password")

这将添加两个必需的位置参数。