¿Procesando múltiples valores para una sola opción usando getopt / optparse?

¿Es posible obtener múltiples valores para una opción usando getopt o optparse, como se muestra en el siguiente ejemplo:

./hello_world -c arg1 arg2 arg3 -b arg4 arg5 arg6 arg7 

Tenga en cuenta que el número de valores reales para cada opción (-c, -b) podría ser 1 o 100. No quiero usar: ./hello_world -c "arg1 arg2 arg3" -b "arg4 arg5 arg6 arg7"

Me parece que esto puede no ser posible (y quizás en violación de POSIX), corríjame si me equivoco.

He visto ejemplos donde todas las no opciones al final de la línea ( ./hello_world -c arg1 -b arg1 arg2 arg3 ) se pueden recostackr … pero no para la primera de las múltiples opciones.

Me gustaría que mi aplicación funcionara en una amplia gama de plataformas con diferentes versiones de Python, por lo que no he visto argparser.

    Sí, se puede hacer con optparse.

    Esto es un ejemplo:

     ./test.py --categories=aaa --categories=bbb --categories ccc arg1 arg2 arg3 

    que imprime:

     arguments: ['arg1', 'arg2', 'arg3'] options: {'categories': ['aaa', 'bbb', 'ccc']} 

    Ejemplo de trabajo completo a continuación:

     #!/usr/bin/env python import os, sys from optparse import OptionParser from optparse import Option, OptionValueError VERSION = '0.9.4' class MultipleOption(Option): ACTIONS = Option.ACTIONS + ("extend",) STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",) TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",) ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("extend",) def take_action(self, action, dest, opt, value, values, parser): if action == "extend": values.ensure_value(dest, []).append(value) else: Option.take_action(self, action, dest, opt, value, values, parser) def main(): PROG = os.path.basename(os.path.splitext(__file__)[0]) long_commands = ('categories') short_commands = {'cat':'categories'} description = """Just a test""" parser = OptionParser(option_class=MultipleOption, usage='usage: %prog [OPTIONS] COMMAND [BLOG_FILE]', version='%s %s' % (PROG, VERSION), description=description) parser.add_option('-c', '--categories', action="extend", type="string", dest='categories', metavar='CATEGORIES', help='comma separated list of post categories') if len(sys.argv) == 1: parser.parse_args(['--help']) OPTIONS, args = parser.parse_args() print "arguments:", args print "options:", OPTIONS if __name__ == '__main__': main() 

    Más información en http://docs.python.org/library/optparse.html#adding-new-actions

    A pesar de las afirmaciones de los otros comentarios, esto es posible con vainilla optparse, al menos a partir de python 2.7. Solo necesitas usar action = “append”. De los documentos :

     parser.add_option("-t", "--tracks", action="append", type="int") 

    Si se ve -t3 en la línea de comandos, optparse hace el equivalente de:

     options.tracks = [] options.tracks.append(int("3")) 

    Si, un poco más tarde, se ve –tracks = 4, lo hace:

     options.tracks.append(int("4")) 

    Perdón por llegar tarde a la fiesta, pero resolví esto con optparse usando la bandera de nargs.

     parser.add_option('-c','--categories', dest='Categories', nargs=4 ) 

    http://docs.python.org/2/library/optparse.html#optparse.Option.nargs

    También vale la pena señalar, que argparse (sugerido por unutbu) ahora es parte de la distribución estándar de Python, mientras que optparse está en desuso.

    Ni getopt ni optparse admiten esto fuera de la caja. Además, en el modo predeterminado (GNU), los argumentos adicionales se tratarán como argumentos intercalados, es decir, estarán disponibles como argumentos sobrantes al final del procesamiento.

    La convención sería requerir la mención repetida del mismo argumento, es decir,

     ./hello_world -c arg1 -c arg2 -c arg3 -b arg4 -b arg5 -b arg6 -b arg7 

    Esto es apoyado

    Si absolutamente quieres que funcione de la manera que especifiques (es decir, tanto -b como -c se extienden hasta el siguiente argumento o el final de la lista de argumentos), entonces puedes hackear algo junto con optparse. Heredar de OptionParser e invalidar _process_short_opts. Si es una de sus opciones, procésela en la subclase, o reenvíe a la clase base.

    Puede hacer esto con el parámetro nargs en argparse que viene con Python2.7, y descargable aquí .

    Creo que es una de las mejoras agregadas a argparse que no está en optparse . Entonces, desafortunadamente, no creo que haya una buena manera de manejar esto con optparse o getopt (que es aún más antiguo).

    Una solución rápida y sucia podría ser renunciar a optparse/getop/argparse y simplemente analizar sys.argv usted mismo.

    O, yendo en la dirección opuesta, podría considerar empaquetar una copia congelada de argparse (~ 88K) (renombrado algo como argparse_static ) con su progtwig, e importarlo de esta manera:

     try: import argparse except ImportError: import argparse_static as argparse 

    De esa manera, el progtwig usará argparse si está instalado, y usará argparse_static si no lo está. Lo mejor de todo es que no tendrá que volver a escribir tanto código como argparse convierte en estándar.

    Otra opción sería definir un separador y procesarlo localmente, como las opciones en el comando de assembly.

    Por ejemplo, si , se puede utilizar como separador:

     ... args, _ = getopt.getopt(sys.argv[1:],'b:') for flag, arg in args: if flag=='-b': all_arguments = arg.split(',') ... $ ./test -b opt1,opt2,opt3 

    Lo mismo para el espacio! Pero entonces sus usuarios tienen que citarlo correctamente.

     $ ./test -b 'opt1 opt2 opt3' 

    Una más fácil:

     make_option( "-c", "--city", dest="cities", action="append", default=[], help="specify cities", ) 

    La acción de anexar es la solución más fácil para este problema.