Cómo codificar las opciones combinacionales de argparse en Python

Me ha preocupado este pequeño pedazo de actividad por completar. Hice algún experimento, pero no pude lograr el resultado.

Requisito:

test2.py [-c/-v] -f 

Uso o Reglas:

  1. -c (comparar) toma 2 parametros.

    -v (verificar) toma 1 parámetro.

    Cualquiera de estos dos debe estar presente, pero no ambos .

  2. -f es un parámetro obligatorio (nombre del archivo de salida).

Salida:

Soy capaz de obtener la salida deseada como se muestra a continuación

 kp@kp:~/Study/scripts$ ./test.py -c P1 P2 -fp kp@kp:~/Study/scripts$ ./test.py -v P1 -fp kp@kp:~/Study/scripts$ ./test.py -v P1 usage: test.py   test.py: error: argument -f/--file is required kp@kp:~/Study/scripts$ ./test.py -c P1 P2 usage: test.py   test.py: error: argument -f/--file is required kp@kp:~/Study/scripts$ 

El problema es:

Cuando usas, test.py -h ,
1. La salida no indicará que -c / -v cualquiera de ellos es obligatorio pero no ambos . Indica que todos los argumentos son opcionales.
2. La salida indicará la opción -f bajo argumentos opcionales que es incorrecta. -f es un argumento obligatorio y quiero mostrar argumentos opcionales externos.

Cómo cambiar el script para que la salida de la opción -h sea más fácil de usar (sin ninguna validación externa)

 usage: test.py   Package Compare/Verifier tool. optional arguments: -h, --help show this help message and exit -f outFileName, --file outFileName File Name where result is stored. -c Package1 Package2, --compare Package1 Package2 Compare two packages. -v Package, --verify Package Verify Content of package. kiran@kiran-laptop:~/Study/scripts$ 

Código:

Estoy usando el siguiente código para lograr la salida,

 #!/usr/bin/python import sys import argparse def main(): usage='%(prog)s  ' description='Package Compare/Verifier tool.' parser = argparse.ArgumentParser(usage=usage,description=description) parser.add_argument('-f','--file',action='store',nargs=1,dest='outFileName',help='File Name where result is stored.',metavar="outFileName",required=True) group = parser.add_mutually_exclusive_group(required=True) group.add_argument('-c','--compare',action='store',nargs=2,dest='packageInfo',help='Compare two packages.',metavar=("Package1","Package2")) group.add_argument('-v','--verify',action='store',nargs=1,dest='packageName',help='Verify Content of package.',metavar='Package') args = parser.parse_args() if __name__ == "__main__": main() 

¿Qué resultado exacto estás buscando? No estoy al tanto de ninguna syntax estándar para denotar la exclusividad mutua en un resultado de –help, y es probable que sea confuso para sus usuarios si se crea uno. También asumo que argparse no admite una syntax para ello (ya que si lo hiciera, ya estaría funcionando).

Le sugiero que sea sencillo y simplemente explique a sus usuarios la exclusión mutua en la ayuda para cada uno de los argumentos. Así que cambia sus cadenas de ayuda de la siguiente manera:

 -c Package1 Package2, --compare Package1 Package2 Compare two packages (may not be used with -v). -v Package, --verify Package Verify Content of package (may not be used with -c). 

Eso es extremadamente obvio y razonablemente conciso.

Otra alternativa sería simplemente no mencionarlo, y hacer que el usuario descubra que son mutuamente exclusivos al tratar de usarlos simultáneamente (argparse genera automáticamente un error fácil de usar como ” PROG: error: argument -c: not allowed with argument -v “).

Establezca el nombre del archivo como un argumento posicional y deje que argparse establezca su propio mensaje de uso:

 $ python so.py --help usage: so.py [-h] [-c Package1 Package2 | -v Package] outFileName 

El nombre del archivo debe ser posicional, y debe dejar que argparse escriba su propio mensaje de uso.

Código

 #!/usr/bin/python import sys import argparse def main(): description='Package Compare/Verifier tool.' parser = argparse.ArgumentParser(description=description, epilog='--compare and --verify are mutually exclusive') parser.add_argument('f',action='store',nargs=1, help='File Name where result is stored.', metavar="outFileName") group = parser.add_mutually_exclusive_group(required=False) group.add_argument('-c','--compare',action='store',nargs=2,dest='packageInfo',help='Compare two packages.',metavar=("Package1","Package2")) group.add_argument('-v','--verify',action='store',nargs=1,dest='packageName',help='Verify Content of package.',metavar='Package') args = parser.parse_args() if __name__ == "__main__": main() 

Mensaje de ayuda

 $ python so.py --help usage: so.py [-h] [-c Package1 Package2 | -v Package] outFileName Package Compare/Verifier tool. positional arguments: outFileName File Name where result is stored. optional arguments: -h, --help show this help message and exit -c Package1 Package2, --compare Package1 Package2 Compare two packages. -v Package, --verify Package Verify Content of package. --compare and --verify are mutually exclusive 

Creo que la queja básica es con los positional arguments predeterminados y los nombres de grupo de positional arguments optional arguements . En la help , optional arguments significa: requires a flag like -f or --file ; positional arguments significa it is identified by position . Con los valores predeterminados, las positionals son necesarias y las optionals son opcionales (no necesarias). Pero el usuario puede cambiar eso con un atributo required , dando lugar a una terminología confusa.

Una forma de evitar esto es definir sus propios grupos de argumentos. Estos grupos afectan el diseño de la help , pero no tienen efecto en el análisis. Tampoco afectan la línea de usage .

 def main(): description='Package Compare/Verifier tool.' parser = argparse.ArgumentParser(usage=None,description=description) maingroup = parser.add_argument_group(title='required') maingroup.add_argument('-f','--file',nargs=1,dest='outFileName',help='File Name where result is stored.',metavar="outFileName",required=True) exgroup = parser.add_argument_group(title='one or the other') group = exgroup.add_mutually_exclusive_group(required=True) group.add_argument('-c','--compare',nargs=2,dest='packageInfo',help='Compare two packages.',metavar=("Package1","Package2")) group.add_argument('-v','--verify',nargs=1,dest='packageName',help='Verify Content of package.',metavar='Package') args = parser.parse_args() 

produce:

 usage: stack5603364.py [-h] -f outFileName (-c Package1 Package2 | -v Package) Package Compare/Verifier tool. optional arguments: -h, --help show this help message and exit required: -f outFileName, --file outFileName File Name where result is stored. one or the other: -c Package1 Package2, --compare Package1 Package2 Compare two packages. -v Package, --verify Package Verify Content of package. 

El grupo mutually_exclusive_group afecta solo a la línea de usage .

 (-c Package1 Package2 | -v Package) 

muestra un grupo donde se requiere una de las opciones.

 [-c Package1 Package2 | -v Package] 

Sería un grupo opcional. [] se utilizan para marcar argumentos opcionales (en el sentido ‘no requerido’). Observe cómo -h sigue siendo etiquetado.

http://bugs.python.org/issue9694 es el problema relacionado de Python, donde el autor argparse favorece este enfoque argument_group .