社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

python argparse:增加参数和描述之间的空间

Yuri S. Cherkasov • 5 年前 • 1696 次点击  

我在用蟒蛇3 argparse 用于复杂的命令行界面。很多争论,其中一些是“冗长”的,以避免误解。

parser = argparse.ArgumentParser(description='Command-line interface')
parser.add_argument('--long-param-one',
                    help='Long param one description',
                    dest='lond_param_one',
                    required=True)

parser.add_argument('--long-param-two',
                    help='Long param two description',
                    dest='lond_param_two',
                    required=True)

当参数名足够长并且目标变量也足够长时,当使用 --help

Command-line interface

optional arguments:
  -h, --help            show this help message and exit
  --long-param-one LONG_PARAM_ONE
                        Long param one description
  --long-param-two LONG_PARAM_TWO
                        Long param two description

我的意思是,参数和值在一个字符串上,描述在另一个字符串上,即使控制台右侧有足够的空间,所以可以将其放在一行中。就像fisrt参数 --帮助 做。当您有30-40个参数时,命令行帮助的可读性会变得更糟。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/38998
 
1696 次点击  
文章 [ 2 ]  |  最新文章 5 年前
hpaulj
Reply   •   1 楼
hpaulj    6 年前

当前 HelpFormatter 是否检查 os.environ['COLUMNS'] 用于终端宽度。但这不会动态更新,甚至可能无法设置。

有一个补丁

https://bugs.python.org/file24602/issue13041.patch argparse: terminal width is not detected properly

这显然是最近放进3.8的,看 shutil.get_terminal_size().columns 相反。


至于为什么 argparse 不提供更直接的宽度控制-设计理念已允许自定义 formatter_class 规范,而不是一组(可能)大的格式化参数。大多数参数 ArgumentParser 与解析有关,而不是帮助格式化。其目标是允许完全定制,而不会将输入与许多很少使用的参数混淆。

这个 帮助格式化程序 类不接受几个关键字参数:

HelpFormatter.__init__(self, prog, indent_increment=2, max_help_position=24, width=None)

但是,当前创建格式化程序的方法只是通过 prog 参数。

Giacomo的答案显示了如何指定这些其他参数:

formatter = lambda prog: argparse.HelpFormatter(prog,max_help_position=52)

你也可以子类 帮助格式化程序 自定义格式。这就是备选方案喜欢的 RawTextHelpFormatter 做。

有关自定义格式化程序的详细信息

从argparse文档中:

格式化程序类

ArgumentParser对象允许通过指定备用格式类自定义帮助格式。目前,这类课程有四个:

提供并列出这4个类并不意味着有限制。其他定制是允许的,甚至是鼓励的。

https://bugs.python.org/issue13023 ,史蒂文·贝萨德,原作者 argparse ,提倡编写自己的格式化程序类:

您的解决方案实际上是当前推荐的解决方案——将两个您想要组合的类混合在一起,并将子类作为参数传递。这可能会被记录在某个地方(并测试更多)。

他说的混合是:

class myFormatter(argparse.RawDescriptionHelpFormatter,
                  argparse.ArgumentDefaultsHelpFormatter):
    pass

我提到了 max_help_position 3年前:

https://bugs.python.org/issue25297 max_help_position is not works in argparse library

还有一个问题:

max_help_position is not works in python argparse library

中的其他示例 argparse 允许您提供自定义类或函数的地方包括:

https://docs.python.org/3/library/argparse.html#action-classes https://docs.python.org/3/library/argparse.html#the-namespace-object https://docs.python.org/3/library/argparse.html#customizing-file-parsing https://docs.python.org/3/library/argparse.html#type

我不会担心 最大帮助位置 参数消失或被禁用。如果我在这件事上有任何发言权,像这样的任何提议的变更都将被拒绝,理由是它可能存在向后兼容性问题。

在实践中,最容易更改文档以匹配代码,或者更好地说明模糊的点。在这种情况下, lambda 呼叫 帮助格式化程序 可以被记录下来。我还可以想象定义一个执行相同操作的小函数。在不可能伤害现有用户的情况下,添加功能是最简单的。

Giacomo Alzetta
Reply   •   2 楼
Giacomo Alzetta    6 年前

argparse 默认情况下,限制选项+metavar所占用的最大空间,并将在单独的行上写入帮助消息,即使终端足够大,可以同时容纳这两个选项。

考虑这个示例脚本:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--name', help='help help')
parser.add_argument('--parameter', help='help help')
parser.add_argument('--parameter-name', help='help help')
parser.add_argument('--this-parameter-name', help='help help')
parser.add_argument('--this-is-parameter-name', help='help help')
parser.add_argument('--this-is-a-parameter-name', help='help help')
parser.add_argument('--this-is-a-long-parameter-name', help='help help')
parser.add_argument('--this-is-a-very-long-parameter-name', help='help help')
parser.add_argument('--this-is-a-very-very-long-parameter-name', help='help help')
parser.add_argument('--this-is-a-very-very-very-long-parameter-name', help='help help')

parser.parse_args()

结果输出如下:

usage: a.py [-h] [--name NAME] [--parameter PARAMETER]
            [--parameter-name PARAMETER_NAME]
            [--this-parameter-name THIS_PARAMETER_NAME]
            [--this-is-parameter-name THIS_IS_PARAMETER_NAME]
            [--this-is-a-parameter-name THIS_IS_A_PARAMETER_NAME]
            [--this-is-a-long-parameter-name THIS_IS_A_LONG_PARAMETER_NAME]
            [--this-is-a-very-long-parameter-name THIS_IS_A_VERY_LONG_PARAMETER_NAME]
            [--this-is-a-very-very-long-parameter-name THIS_IS_A_VERY_VERY_LONG_PARAMETER_NAME]
            [--this-is-a-very-very-very-long-parameter-name THIS_IS_A_VERY_VERY_VERY_LONG_PARAMETER_NAME]

optional arguments:
  -h, --help            show this help message and exit
  --name NAME           help help
  --parameter PARAMETER
                        help help
  --parameter-name PARAMETER_NAME
                        help help
  --this-parameter-name THIS_PARAMETER_NAME
                        help help
  --this-is-parameter-name THIS_IS_PARAMETER_NAME
                        help help
  --this-is-a-parameter-name THIS_IS_A_PARAMETER_NAME
                        help help
  --this-is-a-long-parameter-name THIS_IS_A_LONG_PARAMETER_NAME
                        help help
  --this-is-a-very-long-parameter-name THIS_IS_A_VERY_LONG_PARAMETER_NAME
                        help help
  --this-is-a-very-very-long-parameter-name THIS_IS_A_VERY_VERY_LONG_PARAMETER_NAME
                        help help
  --this-is-a-very-very-very-long-parameter-name THIS_IS_A_VERY_VERY_VERY_LONG_PARAMETER_NAME
                        help help

最简单的方法 尝试 要避免此问题,请指定 metavar 显式地使用一个短值,因此改为ov THIS_IS_A_VERY_VERY_VERY_LONG_PARAMETER_NAME 你可以用,比如, X 。例如:

import argparse

parser = argparse.ArgumentParser()
m = 'X'
parser.add_argument('--name', help='help help', metavar=m)
parser.add_argument('--parameter', help='help help', metavar=m)
parser.add_argument('--parameter-name', help='help help', metavar=m)
parser.add_argument('--this-parameter-name', help='help help', metavar=m)
parser.add_argument('--this-is-parameter-name', help='help help', metavar=m)
parser.add_argument('--this-is-a-parameter-name', help='help help', metavar=m)
parser.add_argument('--this-is-a-long-parameter-name', help='help help', metavar=m)
parser.add_argument('--this-is-a-very-long-parameter-name', help='help help', metavar=m)
parser.add_argument('--this-is-a-very-very-long-parameter-name', help='help help', metavar=m)
parser.add_argument('--this-is-a-very-very-very-long-parameter-name', help='help help', metavar=m)

parser.parse_args()

结果是:

usage: a.py [-h] [--name X] [--parameter X] [--parameter-name X]
            [--this-parameter-name X] [--this-is-parameter-name X]
            [--this-is-a-parameter-name X] [--this-is-a-long-parameter-name X]
            [--this-is-a-very-long-parameter-name X]
            [--this-is-a-very-very-long-parameter-name X]
            [--this-is-a-very-very-very-long-parameter-name X]

optional arguments:
  -h, --help            show this help message and exit
  --name X              help help
  --parameter X         help help
  --parameter-name X    help help
  --this-parameter-name X
                        help help
  --this-is-parameter-name X
                        help help
  --this-is-a-parameter-name X
                        help help
  --this-is-a-long-parameter-name X
                        help help
  --this-is-a-very-long-parameter-name X
                        help help
  --this-is-a-very-very-long-parameter-name X
                        help help
  --this-is-a-very-very-very-long-parameter-name X
                        help help

这已经好了很多,但是正如您可以看到的,参数名很长,它仍然不会将所有文本写在一行上。

实现所需目标的唯一方法是指定 formatter_class 并使用 max_help_position 如中所述 this question . 但是,这不是模块的公共API的一部分。我不知道他们什么时候没有向公共API添加至少两个有用的参数。

您可能仍要指定 元变量 :

import argparse

formatter = lambda prog: argparse.HelpFormatter(prog,max_help_position=52)
parser = argparse.ArgumentParser(formatter_class=formatter)
m = 'X'
parser.add_argument('--name', help='help help', metavar=m)
parser.add_argument('--parameter', help='help help', metavar=m)
parser.add_argument('--parameter-name', help='help help', metavar=m)
parser.add_argument('--this-parameter-name', help='help help', metavar=m)
parser.add_argument('--this-is-parameter-name', help='help help', metavar=m)
parser.add_argument('--this-is-a-parameter-name', help='help help', metavar=m)
parser.add_argument('--this-is-a-long-parameter-name', help='help help', metavar=m)
parser.add_argument('--this-is-a-very-long-parameter-name', help='help help', metavar=m)
parser.add_argument('--this-is-a-very-very-long-parameter-name', help='help help', metavar=m)
parser.add_argument('--this-is-a-very-very-very-long-parameter-name', help='help help', metavar=m)

parser.parse_args()

输出将是:

usage: a.py [-h] [--name X] [--parameter X] [--parameter-name X]
            [--this-parameter-name X] [--this-is-parameter-name X]
            [--this-is-a-parameter-name X] [--this-is-a-long-parameter-name X]
            [--this-is-a-very-long-parameter-name X]
            [--this-is-a-very-very-long-parameter-name X]
            [--this-is-a-very-very-very-long-parameter-name X]

optional arguments:
  -h, --help                                        show this help message and
                                                    exit
  --name X                                          help help
  --parameter X                                     help help
  --parameter-name X                                help help
  --this-parameter-name X                           help help
  --this-is-parameter-name X                        help help
  --this-is-a-parameter-name X                      help help
  --this-is-a-long-parameter-name X                 help help
  --this-is-a-very-long-parameter-name X            help help
  --this-is-a-very-very-long-parameter-name X       help help
  --this-is-a-very-very-very-long-parameter-name X  help help

您可能会尝试确定终端的大小(大多数终端都提供 WIDTH COLUMNS env变量,可用于确定 最大帮助位置 在那种情况下那是最好的。


要使所有参数在一行上都有帮助(假设足够大的终端),您需要:

max_help_position >= max(len(param.name)+len(param.metavar) for param in params)