usage store_true parser mutually metavar help float exclusive argumentparser argument python argparse

store_true - python argparse argumentparser()



¿Argparse(python) admite grupos de argumentos que se excluyen mutuamente? (3)

Sólo me topé con este problema yo mismo. Desde mi lectura de los documentos argparse, no parece haber una forma sencilla de lograrlo dentro de argparse. Consideré usar parse_known_args, pero eso pronto equivale a escribir una versión especial de argparse ;-)

Tal vez un informe de error está en orden. Mientras tanto, si está dispuesto a hacer que su usuario escriba un poco más, puede simularlo con subgrupos (como funcionan los argumentos de git y svn), por ejemplo

subparsers = parser.add_subparsers() p_ab = subparsers.add_parser(''ab'') p_ab.add_argument(...) p_cd = subparsers.add_parser(''cd'') p_cd.add_argument(...)

No es lo ideal, pero al menos te da lo bueno de argparse sin demasiada piratería fea. Terminé eliminando los interruptores y simplemente utilizando las operaciones del subparser con los subargumentos necesarios.

Si tengo los argumentos ''-a'', ''-b'', ''-c'', ''-d'' , con la función add_mutually_exclusive_group() mi programa tendrá que usar solo uno de ellos. ¿Hay alguna forma de combinar eso, de modo que el programa acepte solo ''-a 999 -b 999'' o ''-c 999 -d 999'' ?

Edición: añadiendo un programa simple para más claridad:

>>> parser = argparse.ArgumentParser() >>> group = parser.add_mutually_exclusive_group() >>> group.add_argument(''-a'') >>> group.add_argument(''-b'') >>> group.add_argument(''-c'') >>> group.add_argument(''-d'')

Entonces solo ./app.py -a | ./app.py -b | ./app.py -c | ./app.py -d ./app.py -a | ./app.py -b | ./app.py -c | ./app.py -d ./app.py -a | ./app.py -b | ./app.py -c | ./app.py -d puede ser llamado. ¿Es posible tener grupos de exclusión argparse, de modo que solo ./app.py -a .. -b .. | ./app.py -c .. -d .. ./app.py -a .. -b .. | ./app.py -c .. -d .. ser llamado?


EDIT : No importa. Porque argparse hace la horrible elección de tener que crear una opción al invocar group.add_argument . Esa no sería mi elección de diseño. Si estás desesperado por esta función, puedes intentar hacerlo con ConflictsOptionParser :

# exclusivegroups.py import conflictsparse parser = conflictsparse.ConflictsOptionParser() a_opt = parser.add_option(''-a'') b_opt = parser.add_option(''-b'') c_opt = parser.add_option(''-c'') d_opt = parser.add_option(''-d'') import itertools compatible_opts1 = (a_opt, b_opt) compatible_opts2 = (c_opt, d_opt) exclusives = itertools.product(compatible_opts1, compatible_opts2) for exclusive_grp in exclusives: parser.register_conflict(exclusive_grp) opts, args = parser.parse_args() print "opts: ", opts print "args: ", args

Así, cuando lo invocamos, podemos ver que obtenemos el efecto deseado.

$ python exclusivegroups.py -a 1 -b 2 opts: {''a'': ''1'', ''c'': None, ''b'': ''2'', ''d'': None} args: [] $ python exclusivegroups.py -c 3 -d 2 opts: {''a'': None, ''c'': ''3'', ''b'': None, ''d'': ''2''} args: [] $ python exclusivegroups.py -a 1 -b 2 -c 3 Usage: exclusivegroups.py [options] exclusivegroups.py: error: -b, -c are incompatible options.

El mensaje de advertencia no le informa que tanto ''-a'' como ''-b'' son incompatibles con ''-c'' , sin embargo, podría crearse un mensaje de error más apropiado. Más viejo, la respuesta incorrecta a continuación.

EDICIÓN ANTERIOR: [Esta edición es incorrecta, aunque ¿no sería simplemente un mundo perfecto si argparse funcionara de esta manera?] Mi respuesta anterior en realidad fue incorrecta, debería poder hacerlo con argparse especificando un grupo por opciones mutuamente excluyentes . Incluso podemos usar itertools para generalizar el proceso. Y haz que no tengamos que escribir explícitamente todas las combinaciones:

import itertools compatible_opts1 = (''-a'', ''-b'') compatible_opts2 = (''-c'', ''-d'') exclusives = itertools.product(compatible_opts1, compatible_opts2) for exclusive_grp in exclusives: group = parser.add_mutually_exclusive_group() group.add_argument(exclusive_grp[0]) group.add_argument(exclusive_grp[1])


Subparsers?

Similar a la respuesta de unhammer , pero con más control del usuario. Nota: en realidad no he probado este método, pero debería funcionar en teoría y con las capacidades de python.

Puede crear dos analizadores, uno para cada uno de los dos grupos, y usar condicionales para hacer la parte mutuamente exclusiva. Esencialmente, usar argparse para solo una parte del análisis de argumentos. Usando este método, también puede ir más allá de las limitaciones de la respuesta de Unhammer .

# Python 3 import argparse try: parser = argparse.ArgumentParser() parser.add_argument(''-a'') parser.add_argument(''-b'') args = parser.parse_args except argparse.ArgumentError: parser = argparse.ArgumentParser() parser.add_argument(''-c'') parser.add_argument(''-d'') args = parser.parse_args