Compruebe si el argumento opcional argparse está establecido o no


112

Me gustaría comprobar si el usuario ha establecido un argumento opcional argparse o no.

¿Puedo verificar de forma segura usando isset?

Algo como esto:

if(isset(args.myArg)):
    #do something
else:
    #do something else

¿Funciona igual para los argumentos de tipo float / int / string?

Podría establecer un parámetro predeterminado y verificarlo (por ejemplo, establecer myArg = -1, o "" para una cadena, o "NOT_SET"). Sin embargo, el valor que en última instancia quiero usar solo se calcula más adelante en el script. Entonces lo establecería en -1 como predeterminado y luego lo actualizaría a otra cosa más adelante. Esto parece un poco torpe en comparación con simplemente verificar si el valor fue establecido por el usuario.


1
¿Qué sería isset()(pista: Python no es PHP)? ¿Querías decir en hasattr()cambio, quizás? ¿Por qué no configurar argparse para establecer un valor predeterminado para una opción en su lugar?
Martijn Pieters

@MartijnPieters: sí, es cierto. Entonces, ¿puedo simplemente verificar si (args.myArg): ...
Madeleine P. Vincent

Respuestas:


146

Creo que los argumentos opcionales (especificados con --) se inicializan Nonesi no se proporcionan. Entonces puedes probar con is not None. Pruebe el siguiente ejemplo:

import argparse as ap

def main():
    parser = ap.ArgumentParser(description="My Script")
    parser.add_argument("--myArg")
    args, leftovers = parser.parse_known_args()

    if args.myArg is not None:
        print "myArg has been set (value is %s)" % args.myArg

Las pruebas "es Ninguno" y "No es Ninguno" funcionan exactamente como me gustaría y esperaba. Gracias.
Madeleine P. Vincent

39
Desafortunadamente, no funciona, entonces el argumento obtuvo su defaultvalor definido.
kcpr

6
Si desea establecer un default, aún puede establecer nargs='?'y proporcionar un constvalor, como se describe en los documentos . Cuando arg está ausente, defaultse usa, cuando arg se da sin valor, entonces constse usa, de lo contrario se usa el valor dado. Con solo defaulty nargs='?', defaultse usa si no se da, Nonesi se da sin valor, de lo contrario el valor dado.
Ioannis Filippidis

@IoannisFilippidis si usa action= "store_true"o action="store_const", const="yourconst"no puede usar ese argumento para almacenar otro valor. Esto no funcionará si se utilizan valores predeterminados. En el mío, eliminé todos los valores predeterminados de argparser y manejé todo dentro de otra función def defaults():en la que combino ConfigParser, ArgumentParser y los valores predeterminados en el orden que quiero
m3nda

@ erm3nda No mencioné establecer un action. La respuesta no usa un action. Las acciones que menciona están documentadas para comportarse de una manera específica (como observó). Sin embargo, no es necesario definir una acción.
Ioannis Filippidis

37

Como señala @Honza, is Nonees una buena prueba. Es el valor predeterminado defaulty el usuario no puede darle una cadena que lo duplique.

Puede especificar otro default='mydefaultvaluey probarlo. Pero, ¿y si el usuario especifica esa cadena? ¿Eso cuenta como escenario o no?

También puede especificar default=argparse.SUPPRESS. Entonces, si el usuario no usa el argumento, no aparecerá en el argsespacio de nombres. Pero probar eso podría ser más complicado:

args.foo # raises an AttributeError
hasattr(args, 'foo')  # returns False
getattr(args, 'foo', 'other') # returns 'other'

Internamente, parsermantiene una lista seen_actionsy la usa para pruebas 'requeridas' y 'mutuamente_exclusivas'. Pero no está disponible para ti fuera de parse_args.


22

Creo que usar la opción default=argparse.SUPPRESStiene más sentido. Entonces, en lugar de comprobar si el argumento esnot None , se comprueba si el argumento es inel espacio de nombres resultante.

Ejemplo:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--foo", default=argparse.SUPPRESS)
ns = parser.parse_args()

print("Parsed arguments: {}".format(ns))
print("foo in namespace?: {}".format("foo" in ns))

Uso:

$ python argparse_test.py --foo 1
Parsed arguments: Namespace(foo='1')
foo in namespace?: True
No se proporciona el argumento:
$ python argparse_test.py
Parsed arguments: Namespace()
foo in namespace?: False

Esto no me funciona en Python 3.7.5 (Anaconda). Obtengo el resultadotestfoo.py: error: argument --foo: expected one argument
Mike Wise

@MikeWise Si desea usar --foosin un valor (es decir, 1en mi ejemplo), debe especificarlo nargs=0en la add_argumentfunción.
Erasmus Cedernaes

Simplemente copié y pegué su código como se especifica en la respuesta. ¿Quizás deberías editarlo? Terminé usando la action='store_true'respuesta a continuación en su lugar en mi código real.
Mike Wise

@MikeWise, ¿ejecutaste el script como python argparse_test.py --foo 1?
Erasmus Cedernaes

11

Puede comprobar una bandera opcionalmente con pasado store_truey store_falseopciones de acción argumento:

import argparse

argparser = argparse.ArgumentParser()
argparser.add_argument('-flag', dest='flag_exists', action='store_true')

print argparser.parse_args([])
# Namespace(flag_exists=False)
print argparser.parse_args(['-flag'])
# Namespace(flag_exists=True)

De esta manera, no tiene que preocuparse por verificar por condicional is not None. Simplemente busca Trueo False. Lea más sobre estas opciones en los documentos aquí.


1
esto no resuelve saber si un argumento que tiene un valor está establecido o no. el principal problema aquí es saber si el valor de args proviene de defaul = "" o es proporcionado por el usuario.
m3nda

5

Si su argumento es posicional (es decir, no tiene un prefijo "-" o "-", solo el argumento, generalmente un nombre de archivo), entonces puede usar el parámetro nargs para hacer esto:

parser = argparse.ArgumentParser(description='Foo is a program that does things')
parser.add_argument('filename', nargs='?')
args = parser.parse_args()

if args.filename is not None:
    print('The file name is {}'.format(args.filename))
else:
    print('Oh well ; No args, no problems')

3

Aquí está mi solución para ver si estoy usando una variable argparse

import argparse

ap = argparse.ArgumentParser()
ap.add_argument("-1", "--first", required=True)
ap.add_argument("-2", "--second", required=True)
ap.add_argument("-3", "--third", required=False) 
# Combine all arguments into a list called args
args = vars(ap.parse_args())
if args["third"] is not None:
# do something

Esto podría dar más información sobre la respuesta anterior que utilicé y adapté para trabajar en mi programa.


0

Para abordar el comentario de @ kcpr sobre la respuesta (actualmente aceptada) de @Honza Osobne

Desafortunadamente, no funciona, entonces el argumento obtuvo su valor predeterminado definido.

primero se puede verificar si el argumento se proporcionó comparándolo con el Namespaceobjeto y proporcionando la default=argparse.SUPPRESSopción (consulte las respuestas de @ hpaulj y @Erasmus Cedernaes y este documento de python3 ) y si no se ha proporcionado, configúrelo en un valor predeterminado.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--infile', default=argparse.SUPPRESS)
args = parser.parse_args()
if 'infile' in args: 
    # the argument is in the namespace, it's been provided by the user
    # set it to what has been provided
    theinfile = args.infile
    print('argument \'--infile\' was given, set to {}'.format(theinfile))
else:
    # the argument isn't in the namespace
    # set it to a default value
    theinfile = 'your_default.txt'
    print('argument \'--infile\' was not given, set to default {}'.format(theinfile))

Uso

$ python3 testargparse_so.py
argument '--infile' was not given, set to default your_default.txt

$ python3 testargparse_so.py --infile user_file.txt
argument '--infile' was given, set to user_file.txt

0

Muy simple, después de definir la variable args por 'args = parser.parse_args ()', también contiene todos los datos de las variables del subconjunto args. Para verificar si una variable está establecida o no, asumiendo que se usa 'action = "store_true" ...

if args.argument_name:
   # do something
else:
   # do something else
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.