Ejemplo de argparse simple quería: 1 argumento, 3 resultados

La documentación para el módulo de python argparse , aunque excelente, estoy segura, es demasiado para mi pequeño cerebro de principiante ahora mismo. No necesito hacer cálculos matemáticos en la línea de comandos o entrometerme con las líneas de formato en la pantalla o cambiar los caracteres de opción. Todo lo que quiero hacer es “Si arg es A, haz esto, si B hace eso, si ninguno de los anteriores muestra ayuda y abandona” .

Mi comprensión de la pregunta original es doble. Primero, en términos del ejemplo argparse más simple posible, me sorprende que no lo haya visto aquí. Por supuesto, para ser completamente simple, también es todo sobrecarga con poco poder, pero podría comenzar.

 import argparse parser = argparse.ArgumentParser() parser.add_argument("a") args = parser.parse_args() if args.a == 'magic.name': print 'You nailed it!' 

Pero este argumento posicional es ahora requerido. Si lo deja al invocar este progtwig, obtendrá un error sobre los argumentos que faltan. Esto me lleva a la segunda parte de la pregunta original. Matt Wilkie parece querer un solo argumento opcional sin una etiqueta con nombre (las tags –option). Mi sugerencia sería modificar el código anterior de la siguiente manera:

 ... parser.add_argument("a", nargs='?', default="check_string_for_empty") ... if args.a == 'check_string_for_empty': print 'I can tell that no argument was given and I can deal with that here.' elif args.a == 'magic.name': print 'You nailed it!' else: print args.a 

Puede que haya una solución más elegante, pero esto funciona y es minimalista.

Esta es la forma en que lo hago con argparse (con múltiples argumentos):

 parser = argparse.ArgumentParser(description='Description of your program') parser.add_argument('-f','--foo', help='Description for foo argument', required=True) parser.add_argument('-b','--bar', help='Description for bar argument', required=True) args = vars(parser.parse_args()) 

args será un diccionario que contiene los argumentos:

 if args['foo'] == 'Hello': # code here if args['bar'] == 'World': # code here 

En su caso, simplemente agregue un solo argumento.

La documentación argparse es razonablemente buena, pero deja de lado algunos detalles útiles que pueden no ser obvios. (@Diego Navarro ya mencionó algo de esto, pero intentaré ampliar su respuesta ligeramente). El uso básico es el siguiente:

 parser = argparse.ArgumentParser() parser.add_argument('-f', '--my-foo', default='foobar') parser.add_argument('-b', '--bar-value', default=3.14) args = parser.parse_args() 

El objeto que obtiene de parse_args() es un objeto ‘Espacio de nombres’: un objeto cuyas variables miembro reciben su nombre de sus argumentos de línea de comando. El objeto de Namespace es cómo accede a sus argumentos y los valores asociados con ellos:

 args = parser.parse_args() print args.my_foo print args.bar_value 

(Tenga en cuenta que argparse reemplaza ‘-‘ en los nombres de sus argumentos con guiones bajos al nombrar las variables).

En muchas situaciones, es posible que desee utilizar argumentos simplemente como indicadores que no tienen ningún valor. Puedes agregarlos en argparse así:

 parser.add_argument('--foo', action='store_true') parser.add_argument('--no-foo', action='store_false') 

Lo anterior creará variables llamadas ‘foo’ con valor True y ‘no_foo’ con valor False, respectivamente:

 if (args.foo): print "foo is true" if (args.no_foo is False): print "nofoo is false" 

Tenga en cuenta también que puede usar la opción “requerido” al agregar un argumento:

 parser.add_argument('-o', '--output', required=True) 

De esa manera, si omite este argumento en la línea de comandos, argparse le dirá que falta y detiene la ejecución de su script.

Finalmente, tenga en cuenta que es posible crear una estructura de dict de sus argumentos utilizando la función vars , si eso le facilita la vida.

 args = parser.parse_args() argsdict = vars(args) print argsdict['my_foo'] print argsdict['bar_value'] 

Como puede ver, vars devuelve un dict con los nombres de sus argumentos como claves y sus valores como, er, valores.

Hay muchas otras opciones y cosas que puede hacer, pero esto debería cubrir los escenarios de uso más comunes y esenciales.

Matt está preguntando acerca de los parámetros posicionales en argparse, y estoy de acuerdo en que la documentación de Python no se encuentra en este aspecto. No hay un solo ejemplo completo en las ~ 20 páginas impares que muestra tanto el análisis como el uso de parámetros posicionales .

Ninguna de las otras respuestas aquí muestra un ejemplo completo de parámetros posicionales, así que aquí hay un ejemplo completo:

 # tested with python 2.7.1 import argparse parser = argparse.ArgumentParser(description="An argparse example") parser.add_argument('action', help='The action to take (eg install, remove, etc.)') parser.add_argument('foo-bar', help='Hyphens are cumbersome in positional arguments') args = parser.parse_args() if args.action == "install": print("You asked for installation") else: print("You asked for something other than installation") # The following do not work: # print(args.foo-bar) # print(args.foo_bar) # But this works: print(getattr(args, 'foo-bar')) 

Lo que me echó fuera es que argparse convertirá el argumento llamado “–foo-bar” en “foo_bar”, pero un parámetro posicional llamado “foo-bar” permanece como “foo-bar”, por lo que es menos obvio cómo Úsalo en tu progtwig.

Observe las dos líneas cerca del final de mi ejemplo: ninguna de ellas funcionará para obtener el valor del parámetro posicional foo-bar. El primero es obviamente incorrecto (es una expresión aritmética args.foo menos barra), pero el segundo tampoco funciona:

 AttributeError: 'Namespace' object has no attribute 'foo_bar' 

Si desea usar el atributo foo-bar , debe usar getattr , como se ve en la última línea de mi ejemplo. Lo que es una locura es que si intentas usar dest=foo_bar para cambiar el nombre de la propiedad a algo que sea más fácil de acceder, obtendrías un mensaje de error realmente extraño:

 ValueError: dest supplied twice for positional argument 

Así es como funciona el ejemplo anterior:

 $ python test.py usage: test.py [-h] action foo-bar test.py: error: too few arguments $ python test.py -h usage: test.py [-h] action foo-bar An argparse example positional arguments: action The action to take (eg install, remove, etc.) foo-bar Hyphens are cumbersome in positional arguments optional arguments: -h, --help show this help message and exit $ python test.py install foo You asked for installation foo 

Otra introducción sumria, inspirada en este post .

 import argparse # define functions, classes, etc. # executes when your script is called from the command-line if __name__ == "__main__": parser = argparse.ArgumentParser() # # define each option with: parser.add_argument # args = parser.parse_args() # automatically looks at sys.argv # # access results with: args.argumentName # 

Los argumentos se definen con combinaciones de lo siguiente:

 parser.add_argument( 'name', options... ) # positional argument parser.add_argument( '-x', options... ) # single-char flag parser.add_argument( '-x', '--long-name', options... ) # flag with long name 

Las opciones comunes son:

  • help : descripción para este argumento cuando se usa --help .
  • predeterminado : valor predeterminado si se omite el argumento.
  • escriba : si espera un float o int (de lo contrario es str ).
  • dest : asigne un nombre diferente a una bandera (por ejemplo, '-x', '--long-name', dest='longName' ).
    Nota: por defecto --long-name se accede al --long-name args.long_name con args.long_name
  • Acción : para el manejo especial de ciertos argumentos.
    • store_true, store_false : para store_true, store_false booleanos
      '--foo', action='store_true' => args.foo == True
    • store_const : para ser usado con la opción const
      '--foo', action='store_const', const=42 => args.foo == 42
    • count : para opciones repetidas, como en ./myscript.py -vv
      '-v', action='count' => args.v == 2
    • append : para opciones repetidas, como en ./myscript.py --foo 1 --foo 2
      '--foo', action='append' => args.foo == ['1', '2']
  • requerido : si se requiere una bandera, o un argumento posicional no lo es.
  • nargs : por una bandera para capturar n args
    ./myscript.py --foo ab => args.foo = ['a', 'b']
  • opciones : para restringir las entradas posibles (especifique como lista de cadenas, o ints si type=int ).

Tenga en cuenta el tutorial de Argparse en los CÓMO de Python . Comienza con la mayoría de los ejemplos básicos, como este:

 import argparse parser = argparse.ArgumentParser() parser.add_argument("square", type=int, help="display a square of a given number") args = parser.parse_args() print(args.square**2) 

Y avanza hacia los menos básicos.

Hay un ejemplo con una opción predefinida para una opción, como lo que se pregunta:

 import argparse parser = argparse.ArgumentParser() parser.add_argument("square", type=int, help="display a square of a given number") parser.add_argument("-v", "--verbosity", type=int, choices=[0, 1, 2], help="increase output verbosity") args = parser.parse_args() answer = args.square**2 if args.verbosity == 2: print("the square of {} equals {}".format(args.square, answer)) elif args.verbosity == 1: print("{}^2 == {}".format(args.square, answer)) else: print(answer) 

Esto es lo que se me ocurrió en mi proyecto de aprendizaje gracias principalmente a @DMH …

Código de demostración:

 import argparse def main(): parser = argparse.ArgumentParser() parser.add_argument('-f', '--flag', action='store_true', default=False) # can 'store_false' for no-xxx flags parser.add_argument('-r', '--reqd', required=True) parser.add_argument('-o', '--opt', default='fallback') parser.add_argument('arg', nargs='*') # use '+' for 1 or more args (instead of 0 or more) parsed = parser.parse_args() # NOTE: args with '-' have it replaced with '_' print('Result:', vars(parsed)) print('parsed.reqd:', parsed.reqd) if __name__ == "__main__": main() 

Esto puede haber evolucionado y está disponible en línea: command-line.py

Script para darle a este código un entrenamiento: command-line-demo.sh

También puedes usar plac (una envoltura alrededor de argparse ).

Como beneficio adicional, genera instrucciones de ayuda ordenadas – vea más abajo.

Ejemplo de script:

 #!/usr/bin/env python3 def main( arg: ('Argument with two possible values', 'positional', None, None, ['A', 'B']) ): """General help for application""" if arg == 'A': print("Argument has value A") elif arg == 'B': print("Argument has value B") if __name__ == '__main__': import plac plac.call(main) 

Ejemplo de salida:

No hay argumentos proporcionados – example.py :

 usage: example.py [-h] {A,B} example.py: error: the following arguments are required: arg 

Argumento inesperado suministrado – example.py C :

 usage: example.py [-h] {A,B} example.py: error: argument arg: invalid choice: 'C' (choose from 'A', 'B') 

Argumento correcto suministrado – example.py A :

 Argument has value A 

Menú de ayuda completo (generado automáticamente) – example.py -h :

 usage: example.py [-h] {A,B} General help for application positional arguments: {A,B} Argument with two possible values optional arguments: -h, --help show this help message and exit 

Breve explicación:

El nombre del argumento generalmente es igual al nombre del parámetro ( arg ).

La anotación de la tupla después del parámetro arg tiene el siguiente significado:

  • Descripción ( Argument with two possible values )
  • Tipo de argumento: uno de ‘bandera’, ‘opción’ o ‘posicional’ ( positional )
  • Abreviatura ( None )
  • Tipo de valor de argumento – por ejemplo. flotar, cadena ( None )
  • Conjunto restringido de opciones ( ['A', 'B'] )

Documentación:

Para obtener más información sobre el uso de plac, consulte su excelente documentación:

Plac: Analizar la línea de comandos de forma fácil

Para agregar a lo que otros han dicho:

Por lo general, me gusta usar el parámetro ‘dest’ para especificar un nombre de variable y luego usar ‘globals (). Update ()’ para colocar esas variables en el espacio de nombres global.

Uso:

 $ python script.py -i "Hello, World!" 

Código:

 ... parser.add_argument('-i', '--input', ..., dest='inputted_variable',...) globals().update(vars(parser.parse_args())) ... print(inputted_variable) # Prints "Hello, World!"