【问题标题】:Grouping argparse subparser arguments分组 argparse 子解析器参数
【发布时间】:2015-11-08 02:53:30
【问题描述】:

我有一个包含多个命令的脚本,每个命令都使用 add_subparser 获取它自己的一组必需和/或可选参数。

=->test.py -h
usage: test.py [-h] <command> ...

positional arguments:
  <command>   Available Commands
    cmd1      Command 1
    cmd2      Command 2
    cmd3      Command 3
    cmd4      Command 4

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


=->test.py cmd1 -h
usage: test.py cmd1 [-h] --flag1 FLAG1

optional arguments:
  -h, --help     show this help message and exit
  --flag1 FLAG1  Test flag


=->test.py cmd2 -h
usage: test.py cmd2 [-h] [--flag2 FLAG2]

optional arguments:
  -h, --help     show this help message and exit
  --flag2 FLAG2  Test flag

我想以某种方式将这些命令分成组,以便用户看到如下内容:

=->test.py -h
usage: test.py [-h] <command> ...

First Group:
  cmd1      Command 1
  cmd2      Command 2

Second Group:
  cmd3      Command 3
  cmd4      Command 4

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

但是,add_argument_group 和 add_subparsers 似乎不能一起工作。

有什么方法可以做到这一点?

【问题讨论】:

    标签: python argparse


    【解决方案1】:

    你是对的,参数组和子解析器不能一起工作。这是因为子解析器(或者更确切地说是它们的名称)不是参数。

    sp = parser.add_subparsers(...) 命令创建一个参数,或者从技术上讲是argparse.Action 子类的一个实例。这是一个立场论证。 add_parser 命令创建一个parser 对象(即调用argparse.ArgumentParser),并将其连同其名称(和别名)一起添加到此操作所拥有的字典中。名称填充 Action 的 choices 属性。

    subparsers 动作可能属于一个参数组,但由于只能有一个这样的动作,它不能帮助您对帮助行进行分组。

    您可以在一定程度上通过使用描述来控制帮助,并省略子解析器的帮助

    import argparse
    
    description = """
    First Group:
      cmd1      Command 1
      cmd2      Command 2
    
    Second Group:
      cmd3      Command 3
      cmd4      Command 4"""
    
    parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter)
    sp = parser.add_subparsers(title='commands',description=description)
    sp.add_parser('cmd1')
    sp.add_parser('cmd2')
    sp.add_parser('cmd3')
    sp.add_parser('cmd4')
    
    parser.print_help()
    

    生产

    1343:~/mypy$ python stack32017020.py 
    usage: stack32017020.py [-h] {cmd1,cmd2,cmd3,cmd4} ...
    
    optional arguments:
      -h, --help            show this help message and exit
    
    commands:
    
      First Group:
        cmd1      Command 1
        cmd2      Command 2
    
      Second Group:
        cmd3      Command 3
        cmd4      Command 4
    
      {cmd1,cmd2,cmd3,cmd4}
    

    http://bugs.python.org/issue9341 - 允许对 argparse 子命令进行分组

    谈论做你想做的事。我提出的补丁并不是微不足道的。但欢迎您测试它。

    【讨论】:

    • 我在 Python 3.6 中,这 几乎 工作。在结束您的示例输出的 {cmd1,cmd2,cmd3,cmd4} 行下方仍有原始帮助输出的其余部分。关于如何抑制它的任何想法?
    • 我知道这是一个旧评论,但对于任何发现这个添加 help=argparse.SUPPRESS 到 parser.add_subparsers() 的人都可以隐藏描述下方的命令(python 3.9,尚未检查其他版本)
    【解决方案2】:

    我遇到了这个问题,并通过在父解析器中创建一个组和一个函数来解决它,它为给定子解析器的每个子解析器创建一个虚拟组,并将虚拟组的对象替换为所需组,同时保留其地址,因此该组确实属于每个子解析器!

    这是一个带有一点上下文的示例:

    import argparse
    import ctypes
    
    
    parent_parser = argparse.ArgumentParser(description="Redacted")
    
    subparsers = parent_parser.add_subparsers()
    
    subparser_email = subparsers.add_parser("email", parents=[parent_parser], add_help=False)
    subparser_gen = subparsers.add_parser("gen", parents=[parent_parser], add_help=False)
    
    group_emails = subparser_email.add_argument_group("Main inputs")
    group_gen = subparser_gen.add_argument_group("Emails generation")
    group_matchers = parent_parser.add_argument_group("Matchers") # The group we want on each subparser
    
    [...] # add the arguments to your groups here
    
    def add_group_to_subparsers(group: argparse._ArgumentGroup, subparsers: argparse._SubParsersAction, name: str):
        for name, subparser in subparsers._name_parser_map.items():
            dummy_group = subparser.add_argument_group(name)
            ctypes.memmove(id(dummy_group), id(group), object.__sizeof__(dummy_group))
    
    add_group_to_subparsers(group_matchers, subparsers, "Matchers")
    
    parent_parser.parse_args()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-25
      • 2019-04-09
      • 1970-01-01
      • 2017-04-27
      • 2020-09-26
      • 2018-12-31
      • 2011-11-21
      • 1970-01-01
      相关资源
      最近更新 更多