[我正在尝试在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')
我不知道可以做到这一点的任何“本机” 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)
注意:
dest
,以便以后识别所选的次解析器。“ 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)
我更喜欢第一种方法。
希望您觉得有用
import argparse
arg_1 = argparse.ArgumentParser(add_help=False)
foobar = arg_1.add_argument('-a', '--arg', required=True,
help='reusable argument')
arg_1
是parser
对象。当您使用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。