且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-12-03 18:33:34

使用 SUPPRESS 作为子解析器默认值可防止它覆盖父解析器值.SUPPRESS 默认值不会在解析开始时插入到 namespace 中.仅当用户使用该参数时才会写入值.

Using SUPPRESS for the subparser default keeps it from overwriting the parent parser value. A SUPPRESS default is not inserted into the namespace at the start of parsing. A value is written only if the user used that argument.

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)

The patch that last changed this behavior (2014)

https://bugs.python.org/issue9351 子命令上的 argparse set_defaults 应该覆盖***设置默认值

https://bugs.python.org/issue9351 argparse set_defaults on subcommands should override top level set_defaults

还有 https://bugs.python.org/issue27859