¿Cómo incluir un argumento posicional en un grupo argparse mutuamente excluyente?

Sé que eso no tiene sentido múltiples argumentos posicionales en un grupo mutuamente exclusivo porque no se puede decir quién es quién. Pero necesito incluir UN argumento posicional en eso.

Lo que necesito:

$ myprogram -h usage: myprogram [-h] [--delete value | --update value | value] 

Donde value posicional es la acción predeterminada (tipo de “–include”). ( myprogram sin argumentos debe ser válido también).

Mi primer bash (esto no funciona):

 parser = ArgumentParser() group = parser.add_mutually_exclusive_group() group.add_argument('--delete', metavar='value') group.add_argument('--update', metavar='value') group.add_argument('value') 

¿Es eso posible?


Segundo bash:

 parser = ArgumentParser() group = parser.add_mutually_exclusive_group() group.add_argument('--delete', action='store_true') group.add_argument('--update', action='store_true') group.add_argument('--insert', action='store_true', default=True) group.add_argument('value') 

Haría esto un poco diferente:

 parser = ArgumentParser() group = parser.add_mutually_exclusive_group() group.set_defaults(mode='insert') group.add_argument('--delete', action='store_const', dest='mode', const='delete') group.add_argument('--update', action='store_const', dest='mode', const='update') group.add_argument('--insert', action='store_const', dest='mode', const='insert') parser.add_argument('value', nargs='?') args = parser.parse_args() 

Si además desea que el program --delete (sin opción de value ), agregue

 if args.mode != 'insert' and args.value: parser.error("can't {} without a value argument".format(args.mode)) 

Tenga en cuenta que esto significará que el program --insert (sin value ) aún funciona. Podría evitar esto con un poco más de esfuerzo si el mode predeterminado es None , haciendo la comprobación anterior con args.mode is not None , y luego haciendo if args.mode is None: args.mode = 'insert' o similar.

Su syntax se describe más claramente como:

 myprogram {--insert|--update|--delete} value 

donde – --insert valores predeterminados como Verdadero y se requiere valor.

argparse puede hacerte sentir que la syntax deseada debe ajustarse a su modelo cuando algo como

 if args.insert and (args.update or args.delete): parser.print_help() 

Es mucho más obvio.

Agregado en respuesta al comentario:

Aquí está el pseudo-código (lo que significa que no lo probé) que muestra cómo implementaría esto:

 parser.add_argument('--insert', action='store_true') parser.add_argument('--update', action='store_true') parser.add_argument('--delete', action='store_true') parser.add_argument('value') args = parser.parse_args(sys.argv) if ((args.insert and args.delete) or (args.insert and args.update) or (args.update and args.delete)): # can't pick more than one, complain and quit elif not (args.update or args.delete): # they specified no action so assume insert args.insert = True # now one and only one of insert/update/delete is # True and args.value contains the argument 

Espero que eso aclare las cosas.

Hacer que el argumento posicional sea opcional (con ‘?’)

 parser = ArgumentParser() group = parser.add_mutually_exclusive_group() group.add_argument('--delete', metavar='value') group.add_argument('--update', metavar='value') group.add_argument('value', nargs='?') 

el uso es entonces:

 usage: ipython [-h] [--delete value | --update value | value]