float - argparse python boolean
FunciĆ³n de llamada basada en argparse. (4)
Al menos por lo que has descrito, --showtop20
y --listapps
suenan más como subcomandos que como opciones. Suponiendo que este sea el caso, podemos usar subparsers para lograr el resultado deseado. Aquí hay una prueba de concepto:
import argparse
import sys
def showtop20():
print(''running showtop20'')
def listapps():
print(''running listapps'')
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
# Create a showtop20 subcommand
parser_showtop20 = subparsers.add_parser(''showtop20'', help=''list top 20 by app'')
parser_showtop20.set_defaults(func=showtop20)
# Create a listapps subcommand
parser_listapps = subparsers.add_parser(''listapps'', help=''list all available apps'')
parser_listapps.set_defaults(func=listapps)
# Print usage message if no args are supplied.
# NOTE: Python 2 will error ''too few arguments'' if no subcommand is supplied.
# No such error occurs in Python 3, which makes it feasible to check
# whether a subcommand was provided (displaying a help message if not).
# argparse internals vary significantly over the major versions, so it''s
# much easier to just override the args passed to it.
if len(sys.argv) <= 1:
sys.argv.append(''--help'')
options = parser.parse_args()
# Run the appropriate function (in this case showtop20 or listapps)
options.func()
# If you add command-line options, consider passing them to the function,
# e.g. `options.func(options)`
Soy nuevo en Python y actualmente estoy jugando con él. Tengo un script que hace algunas llamadas API a un dispositivo. Me gustaría ampliar la funcionalidad y llamar a diferentes funciones según los argumentos dados al llamar al script.
Actualmente tengo los siguientes:
parser = argparse.ArgumentParser()
parser.add_argument("--showtop20", help="list top 20 by app",
action="store_true")
parser.add_argument("--listapps", help="list all available apps",
action="store_true")
args = parser.parse_args()
También tengo una
def showtop20():
.....
y
def listapps():
....
¿Cómo puedo llamar a la función (y solo a esto) en base al argumento dado? No quiero correr
if args.showtop20:
#code here
if args.listapps:
#code here
ya que quiero mover las diferentes funciones a un módulo más adelante para mantener el archivo ejecutable principal limpio y ordenado.
Como parece que desea ejecutar una función, y solo una, dependiendo de los argumentos proporcionados, le sugiero que use un ./prog command
posicional obligatorio de argumento ./prog command
, en lugar de los argumentos opcionales ( ./prog --command1
o ./prog --command2
).
Entonces, algo como esto debería hacerlo:
FUNCTION_MAP = {''top20'' : my_top20_func,
''listapps'' : my_listapps_func }
parser.add_argument(''command'', choices=FUNCTION_MAP.keys())
args = parser.parse_args()
func = FUNCTION_MAP[args.command]
func()
Hay muchas maneras de desollar a este gato. Aquí hay uno que usa action=''store_const''
(inspirado en el ejemplo de subparser documentado):
p=argparse.ArgumentParser()
p.add_argument(''--cmd1'', action=''store_const'', const=lambda:''cmd1'', dest=''cmd'')
p.add_argument(''--cmd2'', action=''store_const'', const=lambda:''cmd2'', dest=''cmd'')
args = p.parse_args([''--cmd1''])
# Out[21]: Namespace(cmd=<function <lambda> at 0x9abf994>)
p.parse_args([''--cmd2'']).cmd()
# Out[19]: ''cmd2''
p.parse_args([''--cmd1'']).cmd()
# Out[20]: ''cmd1''
Con un dest
compartido, cada acción pone su función ( const
) en el mismo atributo de espacio de nombres. La función es invocada por args.cmd()
.
Y como en el ejemplo de subparsers documentado, esas funciones podrían escribirse para usar otros valores del espacio de nombres.
args = parse_args()
args.cmd(args)
A modo de comparación, aquí está el caso de subparsers equivalentes:
p = argparse.ArgumentParser()
sp = p.add_subparsers(dest=''cmdstr'')
sp1 = sp.add_parser(''cmd1'')
sp1.set_defaults(cmd=lambda:''cmd1'')
sp2 = sp.add_parser(''cmd2'')
sp2.set_defaults(cmd=lambda:''cmd2'')
p.parse_args([''cmd1'']).cmd()
# Out[25]: ''cmd1''
Como se ilustra en la documentación, los subparsers le permiten definir diferentes argumentos de parámetros para cada uno de los comandos.
Y, por supuesto, todas estas declaraciones de argumentos o analizadores add
pueden crearse en un bucle sobre alguna lista o diccionario que empareja una tecla con una función.
Otra consideración importante: ¿qué tipo de uso y ayuda desea? Los diferentes enfoques generan mensajes de ayuda muy diferentes.
Si sus funciones son "lo suficientemente simples", aproveche el parámetro de type
https://docs.python.org/2.7/library/argparse.html#type
type = puede tomar cualquier llamable que tome un solo argumento de cadena y devuelva el valor convertido:
En su ejemplo (incluso si no necesita un valor convertido):
parser.add_argument("--listapps", help="list all available apps",
type=showtop20,
action="store")
Este sencillo script:
import argparse
def showtop20(dummy):
print "{0}/n".format(dummy) * 5
parser = argparse.ArgumentParser()
parser.add_argument("--listapps", help="list all available apps",
type=showtop20,
action="store")
args = parser.parse_args()
Daré:
# ./test.py --listapps test
test
test
test
test
test
test