Python `argparse`:是否有一种干净的方法来添加一个设置多个标志的标志(例如,`--all`”相当于`--x --y`)

ble*_*ach 9 python python-2.7 argparse

我有一些 Pythonargparse命令行处理代码,最初看起来像这样:

import argparse

ap = argparse.ArgumentParser()

ap.add_argument("--x", help = "Set `x`.", action = "store_true", default = False)
ap.add_argument("--y", help = "Set `y`.", action = "store_true", default = False)

ap.add_argument(
  "--all", help = "Equivalent to `--x --y`.",
  action = "store_true", default = False
)

args = ap.parse_args()

if args.all:
  args.x = True
  args.y = True

print "args.x", args.x
print "args.y", args.y
Run Code Online (Sandbox Code Playgroud)

基本思想:我有一些布尔标志可以在特定设置(--x、--y等)上切换,并且我想添加一个方便的选项来切换多个设置 - 例如--all相当于--x --y.

我想避免任何未包含在 中ArgumentParser并在 中完成的命令行处理逻辑parse_args,所以我想出了这个使用自定义argparse.Actions 的解决方案:

import argparse

def store_const_multiple(const, *destinations):
  """Returns an `argparse.Action` class that sets multiple argument
  destinations (`destinations`) to `const`."""
  class store_const_multiple_action(argparse.Action):
    def __init__(self, *args, **kwargs):
      super(store_const_multiple_action, self).__init__(
        metavar = None, nargs = 0, const = const, *args, **kwargs
      )

    def __call__(self, parser, namespace, values, option_string = None):
      for destination in destinations:
        setattr(namespace, destination, const)

  return store_const_multiple_action

def store_true_multiple(*destinations):
  """Returns an `argparse.Action` class that sets multiple argument
  destinations (`destinations`) to `True`."""
  return store_const_multiple(True, *destinations)

ap = argparse.ArgumentParser()

ap.add_argument("--x", help = "Set `x`.", action = "store_true", default = False)
ap.add_argument("--y", help = "Set `y`.", action = "store_true", default = False)

ap.add_argument(
  "--all", help = "Equivalent to `--x --y`.",
  action = store_true_multiple("x", "y")
)

args = ap.parse_args()

print "args.x", args.x
print "args.y", args.y
Run Code Online (Sandbox Code Playgroud)

有没有什么干净的方法可以在argparse没有(0)在parse_args()(第一个示例)或(2)编写自定义argparse.Action(第二个示例)之后进行一些处理的情况下实现我想要的?

use*_*730 1

这已经晚了,并不完全是您想要的,但您可以尝试以下方法:

import argparse

myflags = ['x', 'y', 'z']

parser = argparse.ArgumentParser()
parser.add_argument('--flags', nargs="+", choices=myflags)
parser.add_argument('--all-flags', action='store_const', const=myflags, dest='flags')
args = parser.parse_args()
print(args)
Run Code Online (Sandbox Code Playgroud)

然后调用python myscript.py --flags x y输出这个

Namespace(flags=['x', 'y'])

并调用python myscript.py --all-flags输出这个

Namespace(flags=['x', 'y', 'z'])

但是你必须通过'x' in args.flags而不是简单地检查你的标志args.x