Argparse: compruebe si se han pasado argumentos

Mi secuencia de comandos debería iniciar un modo de demostración, cuando no se proporcionan parámetros. Intenté esto:

args = parser.parse_args()
if len(args) == 0:
    run_demo()
else:
    # evaluate args

Lo que da un *** TypeError: object of type 'Namespace' has no len() as args no hay lista.

¿Cómo lograría lo que quiero?

preguntado el 22 de mayo de 12 a las 09:05

use try excepto para capturar TypeError, para que sepa que no se ha pasado nada -

@avasal, len(args) siempre lanza un TypeError. -

8 Respuestas

Si su objetivo es detectar cuándo sin discusión se le ha dado al comando, luego hacer esto a través de argparse es el enfoque equivocado (como Ben ha señalado muy bien).

¡Piensa de forma sencilla! :-) Creo que argparse no se despobla sys.argv. Asi que, if not len(sys.argv) > 1, entonces el usuario no ha proporcionado ningún argumento.

contestado el 22 de mayo de 12 a las 10:05

funciona y es probablemente la forma mejor/más sencilla de hacerlo :D - cedric julien

Acepté esta respuesta, ya que resuelve mi problema, sin tener que repensar las cosas. => mal de mí ;) - enmarcador

+1 Consejos mucho más prácticos para el problema en cuestión que mi sugerencia para verificar todos los las opciones contra None. - paquet

Tenga en cuenta que esto no funciona para verificar la cantidad de argumentos dados a un subanalizador arbitrariamente anidado. - jonathan komar

argparse le permite configurar (dentro de un objeto de espacio de nombres) todas las variables mencionadas en los argumentos que agregó al analizador, según su especificación y la línea de comando que se analiza. Si establece un valor predeterminado, esas variables tendrán ese valor predeterminado si no se vieron en la línea de comando, no estarán ausentes del objeto Namespace. Y si tu no especifica un valor predeterminado, entonces hay un valor predeterminado implícito de None. Por lo tanto, verificar la longitud del objeto Namespace, sin importar cómo lo haga, no tiene sentido como una forma de verificar si se analizaron los argumentos; siempre debe tener la misma longitud.

En cambio, si sabe que tiene un montón de argumentos sin valores predeterminados y desea verificar si alguno de ellos se configuró en algún valor que no seaNone valor... haz eso. Puede utilizar una lista de comprensión y el vars función para recorrerlos sin tener que duplicar la lista de nombres de la add_argument llamadas, como se muestra en la respuesta de Martijn.

Se vuelve un poco más complicado si algunos de sus argumentos tienen valores predeterminados, y más aún si tienen valores predeterminados que podrían proporcionarse explícitamente en la línea de comando (por ejemplo, un argumento numérico que tiene un valor predeterminado de 0 hace que sea imposible saber el valor predeterminado del usuario proporcionando 0). En ese caso, no estoy seguro de que haya una solución general que siempre funcione sin saber cuáles son los argumentos.

contestado el 22 de mayo de 12 a las 10:05

Si uno realmente necesita el número de argumento (por cualquier motivo). He encontrado este código muy útil (pero no sé cuánto está optimizado, y agradecería cualquier comentario al respecto).

args = parser.parse_args()
print( len( vars(args) ) )

Esta versión solo cuenta los parámetros -xx y no pasa ningún valor adicional.

Si uno quiere todo (también los valores pasados), simplemente use len(sys.argv) como se menciono antes.

Respondido 21 ago 13, 16:08

No use argparse. En su lugar, simplemente use sys.argv. argparse crea un espacio de nombres, por lo que siempre le dará un "dict" con sus valores, según los argumentos que utilizó cuando llamó al script.

Esto es lo que hice en el pasado:

args = parser.parse_args()
if len(sys.argv) == 1:
    parser.print_help()
    sys.exit()
return args

Respondido el 04 de enero de 18 a las 23:01

Sé que es un hilo antiguo, pero encontré una solución más directa que también podría ser útil para otros:

Puede comprobar si se han pasado argumentos:

if any(vars(args).values()):
    # evaluate args

O, si no se han pasado argumentos (tenga en cuenta la not operador):

if not any(vars(args).values()):
    run_demo()

Explicación:

  • parse_args() devuelve un objeto "Espacio de nombres" que contiene cada nombre de argumento y su valor asociado. Ejemplo: Namespace(arg1='myfile.txt', arg2='some/path/to/some/folder')

  • If sin argumentos han sido pasados, parse_args() devolverá el mismo objeto pero con todos los valores como None. Ejemplo: Namespace(arg1=None, arg2=None)

Sin embargo, este objeto no es iterable, por lo que debe usar vars() para convertirlo en un dict para que podamos acceder a los valores.

Finalmente, como ahora tenemos un dict en las manos, podemos obtener todos los valores (en un list), con .values()y utilice el any() función para comprobar si alguno de los valores no es None. Para que quede más claro: any() devoluciones False si no hay un solo valor que no lo sea None, False or 0(consulte los documentos para obtener referencias) en la lista que le ha proporcionado.

Espero eso ayude.

Respondido 23 Jul 19, 16:07

Esto no funcionará si tiene argumentos predeterminados, ya que sobrescribirán elNone. - hkh

Supongamos el siguiente ejemplo para extender el suyo para que esté completo:

#!/usr/bin/env python3

import argparse

...
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('input', nargs='?' action='store')
    parser.add_argument('-l', '--length', type=int, action='store')
    parser.add_argument('-v', '--verbose', action='store_true')
    args = parser.parse_args()
    if (args.input == None and args.length == None):
        parser.print_help()
    else:
        print(args)

if __name__ == '__main__':
    main()

Su objeto Namespace, mencionado por @Ben, en este ejemplo es args. De las cuerdas en parser.add_argument se crea una variable. Puede acceder a través de args.input or args.length or args.verbose. Puede verificar esto ejecutando print(args) que en realidad mostrará algo como esto:

Namespace(input=None, length=None, verbose=False)

ya que verbose está establecido en True, si presente y la entrada y la longitud son solo variables, que no tienen que ser instanciadas (no se proporcionan argumentos).

También puede ser útil group = parser.add_mutually_exclusive_group() si quiere asegurarse, no se pueden proporcionar dos atributos simultáneamente.

Para obtener más información, consulte:

respondido 28 mar '17, 23:03

Creativo 😋. Me gustó la respuesta! - 0xInfección

Expandí el concepto de 2dvisio para contar argumentos que no sean cero o ninguno:

vm_opts = parser.parse_args()
v = vars(vm_opts)
n_args = sum([ 1 for a in v.values( ) if a])

respondido 16 nov., 16:16

Esto es útil si usa unittest para probar algo con argparse, en ese caso la respuesta aceptada puede comportarse mal. - cardamomo

Para el caso más simple en el que desea verificar si se ha pasado un solo tipo de argumento que es el mismo entre todas las entradas, puede hacerlo en tres pasos con argparse y numpy.

import argparse
import numpy as np

args = parser.parse_args()
# namespace to dictionary
args_dict = vars(args)
# unpack values from dictionary, pass to array
values = np.array([*args_dict.values()])
# Check if the defaults have changed
args_indices = np.where(values != default)[0]
# Did we pass any arguments?
if len(values) == len(args_indices):
   print("No arguments were passed")

La longitud se utiliza como proxy para comprobar si cualquier or no se han pasado los argumentos. Si desea saber cuál ha sido aprobado, desempaquetará las claves y verificará el índice modificado.

np.array() acepta operadores lógicos para casos más complejos.

Respondido 05 Feb 21, 15:02

puedes conseguir un Namespace con todos los valores por defecto usando defaults = vars(parser.parse_args([])) - Girardi

Tienes razón, gracias. Puede seleccionar un valor predeterminado de su fragmento de código :) - mobiuscreek

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