【问题标题】:Making argsparse subparsers optional使 argsparse 子解析器成为可选
【发布时间】:2017-05-07 21:33:31
【问题描述】:

所以我有以下代码:

parser = argparse.ArgumentParser(description='Manages anime_list.json', add_help=True, version='0.1')
parser.add_argument('-l', '--list', action='store_true', help='List all anime in file')

subparser = parser.add_subparsers(title='Actions', description='Actions that can be performed', dest='command')

add = subparser.add_parser('=add', help='Add anime entry')
add.add_argument('-n', '--name', type=str, required=False, default='',
                 help='The name of the anime adding. Will be auto filled in if left blank')
add.add_argument('-e', '--episode', type=int, required=False, default=0,
                 help='The last watched episode. Download starts add +1 this episode')
add.add_argument('-u', '--url', type=str, required=True, help='A link to any episode for the anime')

remove = subparser.add_parser('=remove', help='Remove anime entry')
remove.add_argument('-n', '--name', type=str, required=True, default='',
                    help='The name of the anime to remove')

args = parser.parse_args()

我想要的是子解析器是可选的。当用户使用--list 参数时,不必提供子解析器参数。当使用 argsparse 的 -h-v 选项时,解析完成并显示帮助信息或版本号。但是当只使用我自己的-l 时,它会抛出一个异常,说没有提供足够的参数。

我发现一个建议说使用 subparser.required = False 应该使它们成为可选的,但它不起作用。

知道我该怎么做吗?我查了一下,似乎找不到解决办法。

【问题讨论】:

  • 有点跑题了,但是如果你可以使用非标准库,你应该看看docopt。绝对是编写命令行应用程序最优雅的方式。

标签: python


【解决方案1】:

所以我找到了一个解决方案,我认为它不是最佳的,但它有效。

感谢this answer 中的 Matthew。

像下面这样修改代码给我想要的功能。

parser = argparse.ArgumentParser(description='Manages anime_list.json', add_help=True, version='0.1')
parser.add_argument('-l', '--list', action='store_true', help='List all anime in file')    

args, sub_commands = parser.parse_known_args()

if args.list:
    print 'Doing list'
else:
    subparser = parser.add_subparsers(title='Actions', description='Actions that can be performed', dest='command')

    add = subparser.add_parser('=add', help='Add anime entry')
    add.add_argument('-n', '--name', type=str, required=False, default='',
                     help='The name of the anime adding. Will be auto filled in if left blank')
    add.add_argument('-e', '--episode', type=int, required=False, default=0,
                     help='The last watched episode. Download starts add +1 this episode')
    add.add_argument('-u', '--url', type=str, required=True, help='A link to any episode for the anime')

    remove = subparser.add_parser('=remove', help='Remove anime entry')
    remove.add_argument('-n', '--name', type=str, required=True, default='',
                        help='The name of the anime to remove')

    args = parser.parse_args()
    print args

return args

基本上解析已知参数,在这种情况下它将是-l 之一。如果未提供 -l 参数,请添加所需的子解析器并再次解析参数。

如果这样做,您的--help 将不再工作,因为它不会显示子解析器的帮助文本。您必须创建手动帮助功能。

【讨论】:

    【解决方案2】:

    输入default 参数。例如:

    parser.add_argument('-l', '--list', action='store_true', help='List all anime in file', default=False)    
    

    这将存储默认值False,并且仅当提供-l 标志时,列表变量才会为True

    【讨论】:

    • action='store_true 使默认值 False 据我所知默认情况下
    【解决方案3】:

    我使用以下解决方案,我觉得它很干净,它可以帮助我扩展和制作更具体的命令行应用程序。

    1) 使用父解析器和子解析器定义一个主要的通用和标准 argparse。我在主库或在类似但不同的项目中使用的通用类中执行此操作。

    2) 添加一个子解析器来转义常见的 argparse,比如“其他”或类似的东西。

    3) 在特定应用程序中创建第二个 argparser,当第一个参数为“其他”时使用。

    示例: 假设我想始终使用/继承一些常见的子解析器和父级,然后还要添加一些特定于应用程序的解析器。假设标准通用解析器具有以下子解析器:加载、查询、显示、...、其他。

    那么它将适用于:

    python code.py 加载 -arg1 -arg2 ...

    python code.py 显示 -arga -argb ...

    而,当使用“其他”时,它将获取父参数并且什么都不做,因此可以使用其他特定于案例的解析器。

    python code.py 其他 application_specific_command -arg3 -arg4

    显然这不会使子解析器成为可选的,所以它不是一个直接的答案;更多在某些情况下可行的可能替代方案。我认为它提供了一些优势:

    1) 没有很多 if 或 try 的逻辑实现 2) 可以将父 args 传递给应用程序特定的解析器(如果“other”有父项) 3) 允许“other”的一些公共 args,即所有特定于案例的命令4) 维护 args 帮助

    【讨论】:

      猜你喜欢
      • 2017-08-28
      • 2012-01-21
      • 2020-09-26
      • 1970-01-01
      • 1970-01-01
      • 2016-06-04
      • 2019-05-04
      • 2013-10-09
      相关资源
      最近更新 更多