我使用下面的简单代码来解析一些参数;注意,其中一个是必需的。不幸的是,当用户在不提供参数的情况下运行脚本时,显示的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

Parameters starting with - or -- are usually considered optional. All other parameters are positional parameters and as such required by design (like positional function arguments). It is possible to require optional arguments, but this is a bit against their design. Since they are still part of the non-positional arguments, they will still be listed under the confusing header “optional arguments” even if they are required. The missing square brackets in the usage part however show that they are indeed required.

请参见文档:

一般来说,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")

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