支持argparse中子命令之前或之后的全局参数



使用解析器设置parents参数将允许在解析器之间共享公共参数(例如父命令和子命令(。但是,无论调用是否在子命令中指定了参数,当使用具有dest关键字的已指定值属性的参数时,将基本语法分析器应用于父命令和子命令似乎都会用子命令语法分析器的值覆盖父语法分析器的数值。

我如何使用argparse模块来合并父命令和子命令中的选项(即,如果其中一个解析器包含选项,则存储值;如果两个解析器都没有指定选项,则使用默认值,如果两个分析器都指定了选项,则如何处理也无所谓(?

sample.py:

from argparse import ArgumentParser
parser = ArgumentParser(add_help=False) # The "base"
parser.add_argument('-v', '--verbose', dest='verbose', action='store_true')
parser.add_argument('-d', '--dir', dest='dir', default=None)
parser_main = ArgumentParser(parents=[parser])
subparsers = parser_main.add_subparsers(dest='command')
subparsers.add_parser('cmd1', parents=[parser])
args = parser_main.parse_args()
print(str(args))

然后,在外壳中:

> sample.py -v -d abc
Namespace(command=None, dir='abc', verbose=True)
> sample.py -v cmd1 -d abc
Namespace(command='cmd1', dir='abc', verbose=False)
> sample.py -d abc cmd1 -v
Namespace(command='cmd1', dir=None, verbose=True)
> sample.py cmd1 -v -d abc
Namespace(command='cmd1', dir='abc', verbose=True)

使用SUPPRESS作为子解析器默认值可以避免覆盖父解析器值。在解析开始时,SUPPRESS默认值不会插入到namespace中。只有当用户使用了该参数时,才会写入值。

import argparse    
parser = argparse.ArgumentParser()
parser.add_argument('-f', '--foo', default='foobar')
parser.add_argument('-v', '--verbose', action='store_const', default=False, const=True)
sp = parser.add_subparsers(dest='cmd')
sp1 = sp.add_parser('cmd1')
sp1.add_argument('-f', '--foo', default=argparse.SUPPRESS)
sp1.add_argument('-v', '--verbose', action='store_const', default=argparse.SUPPRESS, const=True)
args = parser.parse_args()
print(args)

示例运行:

1833:~/mypy$ python3 stack62904585.py
Namespace(cmd=None, foo='foobar', verbose=False)
1834:~/mypy$ python3 stack62904585.py --foo FOO -v
Namespace(cmd=None, foo='FOO', verbose=True)
1834:~/mypy$ python3 stack62904585.py cmd1 
Namespace(cmd='cmd1', foo='foobar', verbose=False)
1834:~/mypy$ python3 stack62904585.py -v cmd1 -f bar
Namespace(cmd='cmd1', foo='bar', verbose=True)

上次更改此行为的补丁(2014(

https://bugs.python.org/issue9351子命令上的argparse set_defaults应覆盖顶级set_default

此外https://bugs.python.org/issue27859

通过使用dest关键字指定不同的名称,可以将值存储在不同的属性中:

from argparse import ArgumentParser
parser = ArgumentParser(add_help=False) # The "base"
parser.add_argument('-v', '--verbose', dest='verbose', action='store_true')
parser.add_argument('-d', '--dir', dest='dir', default=None)
parser_main = ArgumentParser()
parser_main.add_argument('-v', '--verbose', dest='g_verbose', action='store_true')
parser_main.add_argument('-d', '--dir', dest='g_dir', default=None)
subparsers = parser_main.add_subparsers(dest='command')
subparsers.add_parser('cmd1', parents=[parser])
args = parser_main.parse_args()
verbose = args.verbose or args.g_verbose if hasattr(args, 'verbose') else args.g_verbose
d = (args.g_dir if args.dir is None else args.dir) if hasattr(args, 'dir') else args.g_dir

最新更新