在 argparse 子命令之前或之后支持全局参数 [英] Support global arguments before or after sub-command in argparse

查看:19
本文介绍了在 argparse 子命令之前或之后支持全局参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

设置 parents 参数解析器将允许在解析器之间共享公共参数(例如父母和子命令).但是,当使用通过 dest 关键字,无论调用是否在子命令中指定了参数.

Setting the parents argument with a parser will allow for sharing common arguments between parsers (e.g. parents and sub-commands). But, applying a base parser to both the parent and sub-command appears to overwrite the value from the parent parser with the value from the sub-command parser when using an argument that has specified the value attribute to with a dest keyword, whether or not the invocation has specified the argument in the sub-command.

如何使用argparse 模块进行合并父命令和子命令中的选项(即,如果其中一个解析器包含该选项,则存储该值,如果两个解析器都没有指定该选项,则使用默认值,如果两个解析器都指定了该选项,则如何处理并不重要)?

How can I use argparse module to merge the options in the parent and the sub-command (i.e. store the value if either parser contains the option, use the default if neither parser specifies the option, and it doesn't matter how to handle if both parsers specify the option)?

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 中.仅当用户使用该参数时才会写入值.

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

这篇关于在 argparse 子命令之前或之后支持全局参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆