Argparse:"可选参数"下列出的必需参数?

mor*_*ort 187 python argparse

我使用以下简单代码来解析一些参数; 请注意,其中一个是必需的.不幸的是,当用户在不提供参数的情况下运行脚本时,显示的用法/帮助文本并不表示存在非可选参数,我觉得这非常令人困惑.如何让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 )
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

pok*_*oke 270

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

另见文档:

通常,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'])
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)

  • @ZararMahmud:您在代码的第 24 行传入空参数:`parser.parse_args([])` 相反,使用不带参数的 `parser.parse_args()` 来捕获 sys.argv 的内容。每 [argparse](https://docs.python.org/2/library/argparse.html#parsing-arguments) (2认同)

Kar*_*aen 61

由于我更喜欢​​在可选之前列出必需的参数,我通过以下方式解决它:

    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()
Run Code Online (Sandbox Code Playgroud)

这个输出:

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

required arguments:
  --required_arg REQUIRED_ARG

optional arguments:
  --optional_arg OPTIONAL_ARG
Run Code Online (Sandbox Code Playgroud)

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

  • @Anthony - 你不需要add_argument中的'required = True'.上面的答案只是说明了参数分组. (6认同)
  • 我认为在添加参数时仍需要设置'required'参数. (5认同)
  • 这是否会强制argparse根据需要处理任何参数? (3认同)
  • 正如其他答案中所指出的,使用私有成员“_action_groups”违反了 API 合同,并有在下一个次要版本中破坏的风险。 (2认同)

Ral*_*hyZ 37

建立@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()
Run Code Online (Sandbox Code Playgroud)

这个输出:

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
Run Code Online (Sandbox Code Playgroud)

  • **注意**:这个答案破坏了公开的 API,请检查下面的 [Bryan_D 的答案](/sf/answers/4030753401/)。 (3认同)

Bry*_*n_D 5

再过一次,以@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')
Run Code Online (Sandbox Code Playgroud)

它将显示与上面相同的内容,并且应该在将来的版本中仍然有效:

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
Run Code Online (Sandbox Code Playgroud)

  • _action_groups仅供内部使用。因此,不能保证所有版本之间的兼容性。 (3认同)

use*_*647 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()
Run Code Online (Sandbox Code Playgroud)

将打印出

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
Run Code Online (Sandbox Code Playgroud)

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

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()
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)


att*_*tti 5

注意:根据 Christophe Vu-Brugier 的说法,以下代码从 Python 版本 3.10 开始不起作用。

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

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'])
Run Code Online (Sandbox Code Playgroud)

输出:

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
Run Code Online (Sandbox Code Playgroud)