如何修改Python argparse中位置参数的metavar?

14 投票
2 回答
3162 浏览
提问于 2025-04-17 05:20

argparse 这个包里,metavar 参数用来修改程序显示的帮助信息。下面这个程序并不是为了实际运行,而是用来演示 metavar 参数的行为。

import argparse
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description = "Print a range.")

    parser.add_argument("-range1", nargs = 3, type = int, help = "Specify range with: start, stop, step.", metavar = ("start", "stop", "step"))
    parser.add_argument("-range2", nargs = 3, type = int, help = "Specify range with: start, stop, step.", metavar = "r2")

对应的帮助信息是:

usage: main.py [-h] [-range1 start stop step] [-range2 r2 r2 r2]

Print a range.

optional arguments:
  -h, --help            show this help message and exit
  -range1 start stop step
                        Specify range with: start, stop, step.
  -range2 r2 r2 r2      Specify range with: start, stop, step.

请注意 -range1-range2 之间的区别。显然,-range1 是帮助信息中更推荐的写法。

到目前为止我都能理解。但是,如果我把可选的 -range1 参数改成一个位置参数 range1,那么 argparse 就无法处理 metavar 参数的元组了(会出现 ValueError: too many values to unpack 的错误)。
我唯一能让它工作的方式就是像 -range2 那样做。但那样的话,帮助信息就远不如 -range1 的情况好。

有没有办法让位置参数的帮助信息和 -range1 一样好,而不是像可选参数那样呢?

2 个回答

5

不过,如果我把可选的-range1参数改成位置参数range1,argparse就无法处理metavar参数的元组了(ValueError: 值太多,无法拆分)。

argparse不应该出现这个“值太多,无法拆分”的错误信息。这个错误是由metavar, = self._metavar_formatter(action, default)(1)产生的。通常这个函数会返回一个单一的列表或元组,但在你的情况下,它返回了一个元组metavar。它应该给出更清晰的错误信息(比如位置参数不允许使用元组metavar?),或者优雅地调整metavar(比如start|stop|step?)。另一种选择是在帮助信息中使用默认的metavar,而不是元组。

元组metavar在使用行上是可以正常工作的。

我觉得帮助信息的格式是考虑到统一的位置参数来写的。在使用行上可能会显示X [X [X ...]],但在帮助行上只显示X ... X的描述

你的三个项目有不同的名称,所以unutbu建议的三个独立的位置参数,可能正是argparse设计者的初衷。

这个问题已经被提出来了(但还没有修复)

http://bugs.python.org/issue14074 “argparse允许位置参数的nargs>1,但不允许metavar是一个元组”

7

这样怎么样:

import argparse
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description = "Print a range.")

    parser.add_argument("start", type = int, help = "Specify start.", )
    parser.add_argument("stop", type = int, help = "Specify stop.", )
    parser.add_argument("step", type = int, help = "Specify step.", )

    args=parser.parse_args()
    print(args)

这样会得到:

% test.py -h
usage: test.py [-h] start stop step

Print a range.

positional arguments:
  start       Specify start.
  stop        Specify stop.
  step        Specify step.

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

撰写回答