Tengo un código de procesamiento de línea de comandos de Python argparse que inicialmente se veía así:
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 La idea básica: tengo algunas banderas booleanas que alternan en una configuración particular ( --x , --y , etc.), y quiero agregar una opción conveniente que alterna varias configuraciones, por ejemplo, --all es equivalente a --x --y .
Quería evitar tener una lógica de procesamiento de línea de comandos que no estuviera contenida en ArgumentParser y hecha en parse_args , así que se me ocurrió esta solución usando argparse.Action s personalizados:
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 ¿Hay alguna forma limpia de lograr lo que quiero con argparse sin (0) hacer algún procesamiento después de parse_args() (primer ejemplo) o (2) escribir un argparse.Action personalizado (segundo ejemplo)?
Esto es tarde y no es exactamente lo que querías, pero aquí hay algo que puedes probar:
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) Luego, llamar a python myscript.py --flags xy genera esto
Namespace(flags=['x', 'y'])
Y llamar a python myscript.py --all-flags genera esto
Namespace(flags=['x', 'y', 'z'])
Pero tendrá que verificar sus banderas a través 'x' in args.flags lugar de simplemente args.x