from example español python command-line command-line-arguments

python - example - ¿Cuál es la mejor manera de analizar argumentos de línea de comando?



python input arguments from command line (13)

Usando docopt

Desde 2012 Python tiene un módulo muy fácil, potente y realmente genial para el análisis de argumentos llamado docopt . Funciona con Python 2.6 a 3.5 y no necesita instalación (simplemente cópielo). Aquí hay un ejemplo tomado de su documentación:

"""Naval Fate. Usage: naval_fate.py ship new <name>... naval_fate.py ship <name> move <x> <y> [--speed=<kn>] naval_fate.py ship shoot <x> <y> naval_fate.py mine (set|remove) <x> <y> [--moored | --drifting] naval_fate.py (-h | --help) naval_fate.py --version Options: -h --help Show this screen. --version Show version. --speed=<kn> Speed in knots [default: 10]. --moored Moored (anchored) mine. --drifting Drifting mine. """ from docopt import docopt if __name__ == ''__main__'': arguments = docopt(__doc__, version=''Naval Fate 2.0'') print(arguments)

Así que esto es todo: 2 líneas de código más su cadena de documentación que es esencial y obtendrá sus argumentos analizados y disponibles en su objeto de argumentos. Te dije que es genial, ¿verdad ?-)

Usando python-fire

Desde 2017, python-fire tiene otro genial módulo que puede proporcionar una interfaz CLI para su código con usted haciendo un análisis de cero argumentos. Aquí hay un ejemplo simple de la documentación (este pequeño programa expone la función double a la línea de comando):

import fire class Calculator(object): def double(self, number): return 2 * number if __name__ == ''__main__'': fire.Fire(Calculator)

Desde la línea de comando, puede ejecutar:

> calculator.py double 10 20 > calculator.py double --number=15 30

Impresionante ¿no?

¿Cuál es el método o biblioteca más fácil , más flexible y más flexible para analizar argumentos de línea de comando de Python?


Aquí hay un método, no una biblioteca, que parece funcionar para mí.

Los objetivos aquí son ser concisos, cada argumento analizado por una sola línea, los args se alinean para su legibilidad, el código es simple y no depende de ningún módulo especial (solo os + sys), advierte sobre argumentos faltantes o desconocidos con gracia , utilice un bucle simple para / range () y funciona en python 2.xy 3.x

Se muestran dos banderas de alternancia (-d, -v) y dos valores controlados por argumentos (-i xxx y -o xxx).

import os,sys def HelpAndExit(): print("<<your help output goes here>>") sys.exit(1) def Fatal(msg): sys.stderr.write("%s: %s/n" % (os.path.basename(sys.argv[0]), msg)) sys.exit(1) def NextArg(i): ''''''Return the next command line argument (if there is one)'''''' if ((i+1) >= len(sys.argv)): Fatal("''%s'' expected an argument" % sys.argv[i]) return(1, sys.argv[i+1]) ### MAIN if __name__==''__main__'': verbose = 0 debug = 0 infile = "infile" outfile = "outfile" # Parse command line skip = 0 for i in range(1, len(sys.argv)): if not skip: if sys.argv[i][:2] == "-d": debug ^= 1 elif sys.argv[i][:2] == "-v": verbose ^= 1 elif sys.argv[i][:2] == "-i": (skip,infile) = NextArg(i) elif sys.argv[i][:2] == "-o": (skip,outfile) = NextArg(i) elif sys.argv[i][:2] == "-h": HelpAndExit() elif sys.argv[i][:1] == "-": Fatal("''%s'' unknown argument" % sys.argv[i]) else: Fatal("''%s'' unexpected" % sys.argv[i]) else: skip = 0 print("%d,%d,%s,%s" % (debug,verbose,infile,outfile))

El objetivo de NextArg () es devolver el siguiente argumento mientras se comprueban los datos faltantes, y ''skip'' omite el ciclo cuando se usa NextArg (), manteniendo el análisis del marcador en líneas.


Casi todo el mundo está usando getopt

Aquí está el código de ejemplo para el documento:

import getopt, sys def main(): try: opts, args = getopt.getopt(sys.argv[1:], "ho:v", ["help", "output="]) except getopt.GetoptError: # print help information and exit: usage() sys.exit(2) output = None verbose = False for o, a in opts: if o == "-v": verbose = True if o in ("-h", "--help"): usage() sys.exit() if o in ("-o", "--output"): output = a

Entonces, en una palabra, así es como funciona.

Tienes dos tipos de opciones. Aquellos que están recibiendo argumentos, y aquellos que son como interruptores.

sys.argv es más o menos tu char** argv en C. Al igual que en C, te saltas el primer elemento que es el nombre de tu programa y analiza solo los argumentos: sys.argv[1:]

Getopt.getopt lo analizará de acuerdo con la regla que das en el argumento.

"ho:v" aquí describe los argumentos cortos: -ONELETTER . El : significa que -o acepta un argumento.

Finalmente ["help", "output="] describe argumentos largos ( --MORETHANONELETTER ). La salida = una vez más significa que la salida acepta un argumento.

El resultado es una lista de pareja (opción, argumento)

Si una opción no acepta ningún argumento (como - --help aquí) la parte arg es una cadena vacía. Por lo general, quiere hacer un bucle en esta lista y probar el nombre de la opción como en el ejemplo.

espero que esto te ayude.


Creo que la mejor manera para proyectos más grandes es optparse, pero si estás buscando una manera fácil, tal vez http://werkzeug.pocoo.org/documentation/script es algo para ti.

from werkzeug import script # actions go here def action_foo(name=""): """action foo does foo""" pass def action_bar(id=0, title="default title"): """action bar does bar""" pass if __name__ == ''__main__'': script.run()

Así que, básicamente, cada función action_ * está expuesta a la línea de comandos y se genera un bonito mensaje de ayuda de forma gratuita.

python foo.py usage: foo.py <action> [<options>] foo.py --help actions: bar: action bar does bar --id integer 0 --title string default title foo: action foo does foo --name string


En caso de que lo necesite, esto puede ser útil si necesita obtener argumentos Unicode en Win32 (2K, XP, etc.):

from ctypes import * def wmain(argc, argv): print argc for i in argv: print i return 0 def startup(): size = c_int() ptr = windll.shell32.CommandLineToArgvW(windll.kernel32.GetCommandLineW(), byref(size)) ref = c_wchar_p * size.value raw = ref.from_address(ptr) args = [arg for arg in raw] windll.kernel32.LocalFree(ptr) exit(wmain(len(args), args)) startup()


La nueva moda de la cadera es argparse por these razones. argparse> optparse> getopt

actualización: a partir de py2.7 argparse forma parte de la biblioteca estándar y optparse está en desuso.


Otras respuestas mencionan que argparse es el camino a seguir para el nuevo Python, pero no da ejemplos de uso. Para completar, aquí hay un breve resumen de cómo usar argparse:

1) Inicializar

import argparse # Instantiate the parser parser = argparse.ArgumentParser(description=''Optional app description'')

2) Agregar argumentos

# Required positional argument parser.add_argument(''pos_arg'', type=int, help=''A required integer positional argument'') # Optional positional argument parser.add_argument(''opt_pos_arg'', type=int, nargs=''?'', help=''An optional integer positional argument'') # Optional argument parser.add_argument(''--opt_arg'', type=int, help=''An optional integer argument'') # Switch parser.add_argument(''--switch'', action=''store_true'', help=''A boolean switch'')

3) Parse

args = parser.parse_args()

4) Acceso

print("Argument values:") print(args.pos_arg) print(args.opt_pos_arg) print(args.opt_arg) print(args.switch)

5) Verificar valores

if args.pos_arg > 10: parser.error("pos_arg cannot be larger than 10")

Uso

Uso correcto:

$ ./app 1 2 --opt_arg 3 --switch Argument values: 1 2 3 True

Argumentos incorrectos:

$ ./app foo 2 --opt_arg 3 --switch usage: convert [-h] [--opt_arg OPT_ARG] [--switch] pos_arg [opt_pos_arg] app: error: argument pos_arg: invalid int value: ''foo'' $ ./app 11 2 --opt_arg 3 Argument values: 11 2 3 False usage: app [-h] [--opt_arg OPT_ARG] [--switch] pos_arg [opt_pos_arg] convert: error: pos_arg cannot be larger than 10

Ayuda completa:

$ ./app -h usage: app [-h] [--opt_arg OPT_ARG] [--switch] pos_arg [opt_pos_arg] Optional app description positional arguments: pos_arg A required integer positional argument opt_pos_arg An optional integer positional argument optional arguments: -h, --help show this help message and exit --opt_arg OPT_ARG An optional integer argument --switch A boolean switch


Prefiero Click . Extrae las opciones de administración y permite "(...) crear hermosas interfaces de línea de comandos de forma composable con el código mínimo necesario".

Aquí hay un ejemplo de uso:

import click @click.command() @click.option(''--count'', default=1, help=''Number of greetings.'') @click.option(''--name'', prompt=''Your name'', help=''The person to greet.'') def hello(count, name): """Simple program that greets NAME for a total of COUNT times.""" for x in range(count): click.echo(''Hello %s!'' % name) if __name__ == ''__main__'': hello()

También genera automáticamente páginas de ayuda muy formateadas:

$ python hello.py --help Usage: hello.py [OPTIONS] Simple program that greets NAME for a total of COUNT times. Options: --count INTEGER Number of greetings. --name TEXT The person to greet. --help Show this message and exit.


Prefiero optparse a getopt. Es muy declarativo: le dices los nombres de las opciones y los efectos que deberían tener (por ejemplo, establecer un campo booleano), y te devuelve un diccionario poblado de acuerdo con tus especificaciones.

http://docs.python.org/lib/module-optparse.html


Utilice optparse que viene con la biblioteca estándar. Por ejemplo:

#!/usr/bin/env python import optparse def main(): p = optparse.OptionParser() p.add_option(''--person'', ''-p'', default="world") options, arguments = p.parse_args() print ''Hello %s'' % options.person if __name__ == ''__main__'': main()

Fuente: uso de Python para crear herramientas de línea de comandos de UNIX

Sin embargo, a partir de Python 2.7 optparse está en desuso, consulte: ¿Por qué usar argparse en lugar de optparse?


consoleargs merece ser mencionado aquí. Es muy fácil de usar. Echale un vistazo:

from consoleargs import command @command def main(url, name=None): """ :param url: Remote URL :param name: File name """ print """Downloading url ''%r'' into file ''%r''""" % (url, name) if __name__ == ''__main__'': main()

Ahora en la consola:

% python demo.py --help Usage: demo.py URL [OPTIONS] URL: Remote URL Options: --name -n File name % python demo.py http://www.google.com/ Downloading url ''''http://www.google.com/'''' into file ''None'' % python demo.py http://www.google.com/ --name=index.html Downloading url ''''http://www.google.com/'''' into file ''''index.html''''


Esta respuesta sugiere optparse que es apropiado para las versiones anteriores de Python. Para Python 2.7 y superior, argparse reemplaza optparse . Vea esta respuesta para más información.

Como señalaron otras personas, es mejor que vayas con optparse sobre getopt. getopt es más o menos un mapeo uno a uno de las funciones estándar de la biblioteca getopt (3) C, y no es muy fácil de usar.

optparse, aunque es un poco más detallado, está mucho mejor estructurado y es más simple de extender más adelante.

Aquí hay una línea típica para agregar una opción a su analizador:

parser.add_option(''-q'', ''--query'', action="store", dest="query", help="query string", default="spam")

Habla bastante por sí mismo; en el momento del procesamiento, aceptará -q o --query como opciones, almacenará el argumento en un atributo llamado consulta y tendrá un valor predeterminado si no lo especifica. También es autodocumentado, ya que declara el argumento de ayuda (que se usará cuando se ejecuta con -h / - help) allí con la opción.

Usualmente analizas tus argumentos con:

options, args = parser.parse_args()

Esto, de forma predeterminada, analizará los argumentos estándar pasados ​​al script (sys.argv [1:])

options.query se establecerá en el valor que pasó al script.

Usted crea un analizador simplemente haciendo

parser = optparse.OptionParser()

Estos son todos los elementos básicos que necesita. Aquí hay un script de Python completo que muestra esto:

import optparse parser = optparse.OptionParser() parser.add_option(''-q'', ''--query'', action="store", dest="query", help="query string", default="spam") options, args = parser.parse_args() print ''Query string:'', options.query

5 líneas de pitón que te muestran lo básico.

Guárdelo en sample.py y ejecútelo una vez con

python sample.py

y una vez con

python sample.py --query myquery

Más allá de eso, encontrarás que optparse es muy fácil de extender. En uno de mis proyectos, creé una clase de comando que le permite jerarquizar fácilmente los subcomandos en un árbol de comandos. Utiliza optparse fuertemente para encadenar comandos juntos. No es algo que pueda explicar fácilmente en unas pocas líneas, pero siéntase libre de navegar en mi repositorio para la clase principal, así como una clase que lo use y el analizador de opciones


Predeterminado de argumento de línea de comando ligero

Aunque argparse es excelente y es la respuesta correcta para los modificadores de línea de comando y las características avanzadas completamente documentados, puede usar los valores predeterminados de los argumentos de la función para manejar los argumentos posicionales directos de manera muy simple.

import sys def get_args(name=''default'', first=''a'', second=2): return first, int(second) first, second = get_args(*sys.argv) print first, second

El argumento ''nombre'' captura el nombre del script y no se usa. La salida de prueba se ve así:

> ./test.py a 2 > ./test.py A A 2 > ./test.py A 20 A 20

Para scripts simples donde solo quiero algunos valores predeterminados, esto me parece suficiente. Es posible que también desee incluir algún tipo de coerción en los valores de retorno o los valores de línea de comando serán cadenas.