Argparse:必填参数在“可选参数”下列出?

367 投票
7 回答
347071 浏览
提问于 2025-04-18 09:32

我用下面这段简单的代码来解析一些参数;注意其中有一个是必填的。不过,当用户运行这个脚本却没有提供这个参数时,显示的使用说明/帮助文本并没有指出有一个参数是必填的,这让我觉得很困惑。我该怎么做才能让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

7 个回答

5

你不需要去重写可选的组。

只需要这样做:

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
49

再来一次,基于@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
66

这是基于 @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
134

因为我喜欢把必需的参数放在可选参数之前,所以我采用了一些小技巧来实现这个目的:

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 这个选项。

488

--- 开头的参数通常被认为是可选的。而其他的参数则是位置参数,这些参数是必须提供的,就像函数的参数一样。虽然可以让可选参数变成必需的,但这有点违背了它们的设计初衷。因为它们仍然属于非位置参数,所以即使它们是必需的,仍然会在“可选参数”的标题下列出。不过,在用法部分缺少的方括号表明它们实际上是必需的。

你可以查看 文档了解更多信息:

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

撰写回答