Pregunta

¿Cuál es la más fácil, tersest, y la mayoría de los flexible método o biblioteca para analizar Python argumentos de línea de comandos?

¿Fue útil?

Solución

Esta respuesta sugiere optparse cual es apropiado para la edad versiones de Python.Para Python 2.7 o superior, argparse reemplaza optparse.Ver esta respuesta para obtener más información.

Como otras personas, señaló, es mejor ir con optparse más de getopt.getopt es casi un uno-a-uno el mapeo de la norma de getopt(3) funciones de la biblioteca C, y no muy fácil de usar.

optparse, mientras que ser un poco más detallado, es mucho mejor estructurado y más simple para ampliar más adelante.

He aquí una típica línea para añadir una opción para su analizador:

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

Casi habla por sí mismo;en el tiempo de procesamiento, va a accept-p o --consulta como opciones, almacenar el argumento en un atributo llamado de consulta y tiene un valor predeterminado si no se especifica.También es auto-documentado en el que se declara el argumento de la ayuda (que será utilizado cuando se ejecuta con -h/--help) con la opción.

Por lo general, usted analizar sus argumentos con:

options, args = parser.parse_args()

Este será, por defecto, analizar el estándar de argumentos pasados al script (sys.argv[1:])

opciones.consulta a continuación, se establece en el valor que se pasa a la secuencia de comandos.

Crear un analizador simplemente haciendo

parser = optparse.OptionParser()

Todos estos son los elementos básicos que necesita.He aquí una completa secuencia de comandos de Python 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 python que muestran los conceptos básicos.

Guardar en sample.py y ejecute una vez con

python sample.py

y una vez con

python sample.py --query myquery

Más allá de eso, usted encontrará que optparse es muy fácil de extender.En uno de mis proyectos, he creado una clase de Comandos que le permite nido subcomandos en un árbol de comandos fácilmente.Utiliza optparse fuertemente a la cadena de comandos juntos.No es algo que fácilmente se puede explicar en unas pocas líneas, pero siéntase libre de navegar en mi repositorio para la clase principal, así como una clase que usa y la opción analizador de

Otros consejos

Otras respuestas no mencionan que argparse es el camino a seguir para los nuevos Python, pero no se dé ejemplos de uso.La integridad, aquí está un breve resumen de cómo utilizar 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) Analizar

args = parser.parse_args()

4) el Acceso

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

5) Compruebe Que Los Valores De

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

El uso de

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

El uso de docopt

Desde 2012 Python tiene una muy fácil, potente y realmente cool módulo para el argumento de análisis llamado docopt.Funciona con Python 2.6 a 3.5 y no necesita instalación (sólo copia).He aquí un ejemplo tomado de la 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í es este:2 líneas de código, además de su doc cadena que es esenciales y obtener sus argumentos analizados y están disponibles en su objeto de argumentos.He dicho que es genial, no yo ;-)

Usando python-fuego

Desde 2017 python-fuego tiene otro fresco módulo que puede dar a una interfaz CLI de su código con usted haciendo cero argumento de análisis.He aquí un ejemplo simple de la documentación (este pequeño programa que se expone la función double a la línea de comandos):

import fire

class Calculator(object):

  def double(self, number):
    return 2 * number

if __name__ == '__main__':
  fire.Fire(Calculator)

Desde la línea de comandos, puede ejecutar:

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

Impresionante ¿verdad?

La nueva cadera manera es argparse para estos razones.argparse > optparse > getopt

actualización: Como de py2.7 argparse es parte de la librería estándar y optparse está en desuso.

Yo prefiero Haga clic en.Abstrae la gestión de opciones y permite "(...) la creación de hermosos interfaces de línea de comandos en una forma en que se puede componer con tan poco código según sea necesario".

He aquí 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 se genera automáticamente con un formato agradable páginas de ayuda:

$ 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.

Casi todo el mundo está utilizando getopt

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

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

Así, en una palabra, aquí es cómo funciona.

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

sys.argv es bastante parecido a su char** argv en C.Como en C se salta el primer elemento que es el nombre de su programa y analizar sólo los argumentos : sys.argv[1:]

Getopt.getopt analizará de acuerdo a la regla que dar en el argumento.

"ho:v" aquí se describe el corto argumentos : -ONELETTER.El : significa que -o acepta un argumento.

Finalmente ["help", "output="] describe largo ( argumentos --MORETHANONELETTER ).El = después de la salida una vez más, significa que la salida acepta uno de los argumentos.

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

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

Espero que esto te ayudó.

Uso optparse el 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: El uso de Python para crear herramientas de línea de comandos de UNIX

Sin embargo, como el de Python 2.7 optparse está obsoleta, véase: ¿Por qué utilizar argparse en lugar de optparse?

Sólo en caso de que usted podría necesitar, esto puede ayudar si usted necesita para agarrar 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()

Ligero argumento de línea de comandos predeterminados

Aunque argparse es muy grande y es la respuesta correcta para totalmente documentado modificadores de línea de comandos y funciones avanzadas, puede utilizar el argumento de la función por defecto maneja sencillo argumentos posicionales muy simplemente.

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 'nombre' argumento captura el nombre del script y no se utiliza.Prueba de salida se parece a esto:

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

Para secuencias de comandos simples donde solo quiero algunos valores por defecto, esto me parece más que suficiente.También puede ser que desee incluir algún tipo de coacción en los valores de retorno de línea de comandos o valores serán todas las cadenas.

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

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 una de las funciones action_* está expuesto a la línea de comandos y un buen mensaje de ayuda se genera 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

Yo prefiero optparse a getopt.Es muy declarativa:usted dice que los nombres de las opciones y los efectos que debe tener (por ejemplo, la configuración de un campo booleano), y manos a la espalda un diccionario poblada de acuerdo a sus especificaciones.

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

consoleargs merece ser mencionado aquí.Es muy fácil de usar.Check it out:

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''

Argparse código puede ser más largo que el actual código de implementación!

Ese es un problema que me encontré con la mayoría popular argumento de opciones de análisis es que si los parámetros son sólo modesta, el código del documento se convierte en desproporcionadamente grande para el beneficio que aportan.

Un relativo recién llegado a la argumentación de análisis de escena (creo) es plac.

Hace algunos reconoció trade-offs con argparse, pero utiliza documentación en línea y simplemente envuelve alrededor de main() función tipo de función:

def main(excel_file_path: "Path to input training file.",
     excel_sheet_name:"Name of the excel sheet containing training data including columns 'Label' and 'Description'.",
     existing_model_path: "Path to an existing model to refine."=None,
     batch_size_start: "The smallest size of any minibatch."=10.,
     batch_size_stop:  "The largest size of any minibatch."=250.,
     batch_size_step:  "The step for increase in minibatch size."=1.002,
     batch_test_steps: "Flag.  If True, show minibatch steps."=False):
"Train a Spacy (http://spacy.io/) text classification model with gold document and label data until the model nears convergence (LOSS < 0.5)."

    pass # Implementation code goes here!

if __name__ == '__main__':
    import plac; plac.call(main)

He aquí un método, no una biblioteca, que parece funcionar para mí.

Los objetivos aquí son para ser breves, cada uno de los argumentos analizados por una sola línea, los argumentos de la línea para mejorar la legibilidad, el código es sencillo y no depende de ninguna de módulos especiales (sólo os + sys), advierte sobre la falta o desconocido argumentos correctamente, el uso de un simple para/rango() loop, y funciona a través de python 2.x y 3.x

Se muestran son dos alternar banderas (-d, -v), y dos valores controlados por los 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 que la comprobación de los datos que faltan, y 'saltar' salta el bucle cuando NextArg() se utiliza, manteniendo la bandera de análisis de abajo a los trazadores de líneas uno.

Yo extendida de Erco método para permitir requiere argumentos posicionales y de argumentos opcionales.Estos deben preceder al -d, -v, etc.argumentos.

De posición y argumentos opcionales se pueden recuperar con PosArg(i) y OptArg(yo, por defecto), respectivamente.Cuando un argumento opcional se encuentra la posición de inicio de la búsqueda de opciones (por ejemplo,-yo) se mueve 1 por delante para evitar que se produzca un 'inesperado' fatal.

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])

def PosArg(i):
    '''Return positional argument'''
    if i >= len(sys.argv):
        Fatal("'%s' expected an argument" % sys.argv[i])
    return sys.argv[i]

def OptArg(i, default):
    '''Return optional argument (if there is one)'''
    if i >= len(sys.argv):
        Fatal("'%s' expected an argument" % sys.argv[i])
    if sys.argv[i][:1] != '-':
        return True, sys.argv[i]
    else:
        return False, default


### MAIN
if __name__=='__main__':

    verbose = 0
    debug   = 0
    infile  = "infile"
    outfile = "outfile"
    options_start = 3

    # --- Parse two positional parameters ---
    n1 = int(PosArg(1))
    n2 = int(PosArg(2))

    # --- Parse an optional parameters ---
    present, a3 = OptArg(3,50)
    n3 = int(a3)
    options_start += int(present)

    # --- Parse rest of command line ---
    skip = 0
    for i in range(options_start, 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("Number 1 = %d" % n1)
    print("Number 2 = %d" % n2)
    print("Number 3 = %d" % n3)
    print("Debug    = %d" % debug)
    print("verbose  = %d" % verbose)
    print("infile   = %s" % infile)
    print("outfile  = %s" % outfile) 
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top