Argparse - ¿Acción personalizada sin argumento?

class StartAction(argparse.Action):
    def __call__(self, parser, namespace, values, option_string=None):
        print "Hello"

start.add_argument('-s', '--start', action=StartAction)

Sé que normalmente hacer que la acción sea algo así como 'store_true' evitaría el requisito de un argumento, pero ¿hay alguna manera de usar una acción personalizada y aún así no requerir que se pase un argumento?

Entonces lo que quiero es:

python ejemplo.py -s

Hola

preguntado el 12 de junio de 12 a las 18:06

4 Respuestas

Intenta agregar nargs=0 para usted start.add_argument:

start.add_argument('-s', '--start', action=StartAction, nargs=0)

Respondido el 12 de junio de 12 a las 18:06

ValueError: los nargs para las acciones de la tienda deben ser > 0; si no tiene nada que almacenar, las acciones como store true o store const pueden ser más apropiadas: Lucina

No estoy de acuerdo con el comentario de @Lucina. Es posible que desee llamar a una acción personalizada para tener una asignación perfecta entre los argumentos de análisis y las acciones complejas. Prefiero tener objetos de acción que se comporten como los parámetros de la CLI, por lo que tengo polimorfismo entre la interfaz de la CLI y el objeto que la maneja. - Daniel

@Daniel no es una cuestión de "acuerdo". Este es un error que uno puede recibir al configurar nargs=0 - señor elrond

@ReinstateMonica Acepto que existe el error. No estoy de acuerdo con las acciones que sugirió. - Daniel

@Daniel ella no sugirió acciones. Ese es literalmente el mensaje de error. - señor elrond

As mgilson sugirió nargs=0 Hace el truco. Como es intrínseco a tu acción, lo pondría dentro de la acción:

class StartAction(argparse.Action):
    def __init__(self, nargs=0, **kw):
        super().__init__(nargs=nargs, **kw)
    def __call__(self, parser, namespace, values, option_string=None):
        print "Hello"

start.add_argument('-s', '--start', action=StartAction)

Y tiene el comportamiento deseado sin la redundancia de tener que agregar nargs=0 a cada add_argument() llamar. Genial si tiene múltiples argumentos que funcionan de la misma manera.

Sin embargo, los usuarios aún pueden anular el valor predeterminado de nargs=0 lo cual es una tontería para su caso de uso como se demuestra en la pregunta. Así que lo haría cumplir:

class StartAction(argparse.Action):
    def __init__(self, nargs=0, **kw):
        if nargs != 0:
            raise ValueError('nargs for StartAction must be 0; it is '
                             'just a flag.')
        super().__init__(nargs=nargs, **kw)
    def __call__(self, parser, namespace, values, option_string=None):
        print "Hello"

contestado el 23 de mayo de 17 a las 13:05

El primero (sin el control de ejecución) también es exactamente lo que action="store_const" hace: github.com/python/cpython/blob/… - matthijs kooijman

Escribí este ejemplo después de consultar lo anterior y probar diferentes métodos. Aquí hay una clase que implementa la cuenta "Descontar", que es lo opuesto a la acción 'contar'.

import argparse
class Uncount(argparse.Action):
    def __init__(self, option_strings, dest, nargs=0, choices=None, const=None, **kwargs):
        if nargs != 0:
            raise ValueError("no arguments to this parameter are allowed")
        if const is not None:
            raise ValueError("this parameter does not permit constants")
        if choices is not None:
            raise ValueError("no choices to this parameter are allowed")
        super(Uncount, self).__init__(option_strings=option_strings, nargs=nargs, dest=dest,**kwargs)
    def __call__(self, parser, namespace, values, option_string=None):
        value = getattr(namespace, self.dest, 0)
        setattr(namespace, self.dest, value-1)

opts={}
argparser = argparse.ArgumentParser(description='Report on other teams')
argparser.add_argument(
    '-v','--verbose',dest='verbose',default=0,action='count',
    help='increase log level',
)
argparser.add_argument(
    '-q','--quiet',dest='verbose',default=0,action=Uncount,
    help='increase log level',
)

Ejemplos:

>>> argparser.parse_args('-q -q'.split())
Namespace(verbose=-2)
>>> argparser.parse_args('-q -v'.split())
Namespace(verbose=0)
>>> argparser.parse_args('-q -v -v'.split())
Namespace(verbose=1)

Respondido 28 Oct 18, 13:10

Para cualquiera que encuentre esto en 2020: si intenta pasar nargs=0 en el último paquete argparse para python3, se producirá un error con:

ValueError: nargs for store actions must be != 0; if you have nothing to store, actions such as store true or store const may be more appropriate

La solución que probablemente esté buscando es pasar action="store_const" y const=True

Ejemplo:

parser = argparse.ArgumentParser
parser.add_argument('-s', '--start', help='Start script or whatever', action="store_const", const=True)

Esto establecerá el valor de parser.start igual a "True" cuando el parámetro -s se pase a main/the rest of the script.

Respondido 24 Oct 20, 15:10

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.