Imprimir ayuda si no hay argumento posicional?
Pregunta
Estoy haciendo un script bastante simple que toma los siguientes parámetros:
-p --port integer, optional, default 5050
-f --fork boolean, optional, default False
action string, required, needs to be either start or stop
He intentado implementar esto en Argparse, pero no está imprimiendo ayuda cuando no se proporciona una cadena de acción, solo está fallando como feo:
usage: __init__.py [-h] [-p PORT] [-f] {start,stop}
__init__.py: error: argument action: invalid choice: '__init__.py' (choose from 'start', 'stop')
Incluso cuando paso "inicio" o "parar", falla con el mismo mensaje. Aquí está mi código:
parser = argparse.ArgumentParser(description="Start or stop the server.",
epilog="If you don't know what you're doing, run. Run for your life.\n")
parser.add_argument("-p", "--port", type=int, nargs=1, default=5050,
dest="port", help="The port to run the server on.")
parser.add_argument("-f", "--fork", action="store_true", default=False,
dest="fork", help="Fork to background? Default is false.")
parser.add_argument("action", type=str, choices=("start","stop"), help="Whether to 'start' or 'stop' the server.")
¿Qué estoy haciendo mal aquí? Ojalá mis intenciones sean bastante claras de mi código.
Solución
¿Qué versión de Python estás usando? Cuando ejecuto su código con 2.7.1 funciona bien.
$ ./t stop
$ ./t start
$ ./t -f start
$ ./t -f stop
$ ./t -f
usage: someprog [-h] [-p PORT] [-f] {start,stop}
someprog: error: too few arguments
$ ./t -f -p 8080
usage: someprog [-h] [-p PORT] [-f] {start,stop}
someprog: error: too few arguments
$ ./t -f -p 8080 start
Un consejo, si especifica 'prog' en el ctor, puede anularlo usando en eso.py como nombre de archivo
parser = argparse.ArgumentParser(
prog="someprog",
description="Start or stop the server.",
epilog="If you don't know what you're doing, run. Run for your life.\n"
)
También eso es Impresión de uso, pero no la larga ayuda ... podrías hacer algo como esto para hacer las cosas un poco más obvias ...
try:
parser.parse_args()
except Exception e:
print "************************"
parser.print_help()
print "************************"
Otros consejos
Cuando se suministran argumentos no válidos, el módulo argparse está diseñado para imprimir un mensaje de uso y una descripción del problema y luego salir, que es precisamente lo que está sucediendo en su ejemplo.
Si desea que imprima un mensaje de ayuda, deberá manejar este caso usted mismo. Por ejemplo, este código imprimirá el mensaje de ayuda en caso de que no se proporcione ninguna acción:
parser = argparse.ArgumentParser(description="Start or stop the server.",
epilog="If you don't know what you're doing, run. Run for your life.\n",
prog="myserver")
parser.add_argument("-p", "--port", type=int, nargs=1, default=5050,
dest="port", help="The port to run the server on.")
parser.add_argument("-f", "--fork", action="store_true", default=False,
dest="fork", help="Fork to background? Default is false.")
parser.add_argument("action", nargs="?", type=str, choices=("start","stop"),
help="Whether to 'start' or 'stop' the server.")
args = parser.parse_args()
if args.action is None:
parser.print_help()
sys.exit(1)
Si ejecuto esto sin acción, obtengo:
$ python s.py
usage: myserver [-h] [-p PORT] [-f] [{start,stop}]
Start or stop the server.
positional arguments:
{start,stop} Whether to 'start' or 'stop' the server.
optional arguments:
-h, --help show this help message and exit
-p PORT, --port PORT The port to run the server on.
-f, --fork Fork to background? Default is false.
If you don't know what you're doing, run. Run for your life.
Sin embargo, si ejecuto esto con una acción inválida, o un argumento no válido, entonces vuelve al comportamiento previsto del módulo Argparse:
$ python s.py not_valid
usage: myserver [-h] [-p PORT] [-f] [{start,stop}]
myserver: error: argument action: invalid choice: 'not_valid' (choose from 'start', 'stop')