python 中的 CLI 选项是其他两个选项和优先级的集合

CLI option that is an aggregation of two other options and precedence, in python

我正在使用 argparse 来解析我的 Python 脚本中的 CLI 选项。我会创建一个相当于指定另外两个标志的标志。所以

python myscript.py --flagc

等同于

python myscript.py --flaga --flagb

这是我的代码:

args = parser.parse_args()

if args.flagc:
    args.flaga = True
    args.flagb = True

问题是flagaflagb也有相反的标志,no-flagano-flagb

parser.add_argument("--flaga", dest="flaga", action="store_true")
parser.add_argument("--no-flaga", dest="flaga", action="store_false")
parser.set_defaults(flaga=False)

等等。所以我可能会遇到标志优先级的问题。例如,如果我调用脚本:

python myscript.py --flagc --no-flaga

我得到 True for args.flaga,但通常你想要 False,因为最后一个标志优先。

我该如何管理?

是的,通过在解析后处理 flag_c,您丢失了优先级信息。通常该问题支持这种 post 处理,但在这里自定义操作可能是更好的选择。

class MyAction(argparse._StoreTrueAction):
    def __call__(self, parser, namespace, values, option_string=None):
        # adapt from _StoreConst
        # leave the self.dest set; could deactivate
        setattr(namespace, self.dest, self.const)
        setattr(namespace, 'flaga', True)
        setattr(namespace, 'flagb', True)

parser.add_argument("--flagc", action=MyAction)

print(parser.parse_args('--flaga'.split()))
print(parser.parse_args('--flagc'.split()))
print(parser.parse_args('--flagc --no-flaga'.split()))

打印:

1027:~/mypy$ python stack33264649.py 
Namespace(flaga=True, flagb=False, flagc=False)
Namespace(flaga=True, flagb=True, flagc=True)
Namespace(flaga=False, flagb=True, flagc=True)

这是最简单的习惯 class 可以完成这项工作。它利用了其父项设置的默认值(尤其是 nargs=0)。或者它可以基于 _StoreConst 甚至 Action.

我将 setattr(namespace, self.dest, self.const) 留在原处。准确指示 --flagc 是否被调用没有什么坏处。而且它比试图抑制 flagc 默认更简单。

好的,隐藏默认值并不难:

class MyAction(argparse._StoreTrueAction):
    def __init__(self, *args, **kwargs):
        super(MyAction, self).__init__(*args,**kwargs)
        self.default=argparse.SUPPRESS
    def __call__(self, parser, namespace, values, option_string=None):
        setattr(namespace, 'flaga', True)
        setattr(namespace, 'flagb', True)