argparse-修改子命令的父参数的'required'状态

问题描述 投票:0回答:2

[我正在尝试在Python中构建CLI,并且有一个参数(--arg),我想在多个子命令(req和opt)之间重用。

但是一个子命令(req)将必须要求--arg,而另一个(opt)则不需要。如何解决此问题而不必使用相同参数的两个版本?

import argparse
arg_1 = argparse.ArgumentParser(add_help=False)
arg_1.add_argument('-a', '--arg', required=True,
                    help='reusable argument')

parser = argparse.ArgumentParser()
subp = parser.add_subparsers()

cmd_require = subp.add_parser('req', parents=[arg_1],
                                help='this subcommand requires --arg')  
cmd_optional = subp.add_parser('opt', parents=[arg_1],
                                help='this subcommand doesn\'t require --arg')  
python arguments command-line-interface argparse
2个回答
2
投票

我不知道可以做到这一点的任何“本机” argparse功能。但是,我想到了两种解决您问题的方法。

在单独的函数中验证args-有时CLI应用程序会变得复杂,并且通过添加验证器功能,您可以“完成”所需的缺少的argparse功能。

import argparse
arg_1 = argparse.ArgumentParser(add_help=False)
arg_1.add_argument('-a', '--arg', required=False,
                    help='reusable argument')

parser = argparse.ArgumentParser()
subp = parser.add_subparsers(dest='sub_parser')

cmd_require = subp.add_parser('req', parents=[arg_1],
                                help='this subcommand requires --arg')  
cmd_optional = subp.add_parser('opt', parents=[arg_1],
                                help='this subcommand doesn\'t require --arg') 

def validate_args(args):
    print(args)
    if args.sub_parser == 'req' and not args.arg:
        print("Invalid usage! using 'req' requires 'arg'")
        exit(1)

if __name__ == '__main__':
    args = parser.parse_args()
    validate_args(args)

注意:

  1. 我为子解析器使用了dest,以便以后识别所选的次解析器。
  2. 使用argparse,如果未传递可选参数,它将为'None'

“ prepared arguments”-尽管argparse不支持argument对象-您可以通过解压缩字典和元组(* args,** kwargs)来“准备”参数(* args,** kwargs)

import argparse
arg_name = ('-a', '--arg')
arg_dict = {'help': 'reusable argument'}
parser = argparse.ArgumentParser()
subp = parser.add_subparsers()

cmd_require = subp.add_parser('req',
                                help='this subcommand requires --arg')  
cmd_optional = subp.add_parser('opt',
                                help='this subcommand doesn\'t require --arg') 

cmd_optional.add_argument(*arg_name, **arg_dict, required=False)
cmd_require.add_argument(*arg_name, **arg_dict, required=True)

if __name__ == '__main__':
    args = parser.parse_args()
    validate_args(args)

我更喜欢第一种方法。

希望您觉得有用


0
投票
import argparse
arg_1 = argparse.ArgumentParser(add_help=False)
foobar = arg_1.add_argument('-a', '--arg', required=True,
                    help='reusable argument')

arg_1parser对象。当您使用add_argument命令时,它将创建一个Action对象并将其添加到args_1._actions列表中。我刚刚在foobar变量中保存了对它的引用。

parser = argparse.ArgumentParser()
subp = parser.add_subparsers()

parents机制将args_1._actions列表添加到cmd_require._actions列表中。因此foobar将出现在两个子解析器中。它是按引用复制的,这在python中很常见。

cmd_require = subp.add_parser('req', parents=[arg_1],
                                help='this subcommand requires --arg')  
cmd_optional = subp.add_parser('opt', parents=[arg_1],
                                help='this subcommand doesn\'t require --arg') 

foobar.required=False将在属性上关闭,但对于两个解析器都将关闭。当人们想要分配不同的default属性时,我已经看到了这个问题。

parents机制只是一个快捷方式,偶尔会有用,但并非总是如此。它没有做任何特别的事情。只是节省了一点打字。在两个子解析器中,还有许多其他方法可以定义具有相同标志的Action。

  • 两次输入(恐怖!)
  • 复制粘贴
  • 编写实用程序函数以向子解析器添加参数(请参见Larry Wall的Three Virtues
© www.soinside.com 2019 - 2024. All rights reserved.