Argparse argumentos posicionales opcionales?

652

Tengo un script que debe usarse de esta manera: usage: installer.py dir [-h] [-v]

dir es un argumento posicional que se define así:

parser.add_argument('dir', default=os.getcwd())

Quiero dirque sea opcional: cuando no se especifica, debería serlo cwd.

Lamentablemente, cuando no especifico el dirargumento, obtengo Error: Too few arguments.

Waldo Bronchart
fuente

Respuestas:

825

Uso nargs='?'(o nargs='*' si necesitará más de un directorio)

parser.add_argument('dir', nargs='?', default=os.getcwd())

ejemplo extendido:

>>> import os, argparse
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('-v', action='store_true')
_StoreTrueAction(option_strings=['-v'], dest='v', nargs=0, const=True, default=False, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('dir', nargs='?', default=os.getcwd())
_StoreAction(option_strings=[], dest='dir', nargs='?', const=None, default='/home/vinay', type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args('somedir -v'.split())
Namespace(dir='somedir', v=True)
>>> parser.parse_args('-v'.split())
Namespace(dir='/home/vinay', v=True)
>>> parser.parse_args(''.split())
Namespace(dir='/home/vinay', v=False)
>>> parser.parse_args(['somedir'])
Namespace(dir='somedir', v=False)
>>> parser.parse_args('somedir -h -v'.split())
usage: [-h] [-v] [dir]

positional arguments:
  dir

optional arguments:
  -h, --help  show this help message and exit
  -v
Vinay Sajip
fuente
14
¿ Significa ?y *significa lo mismo que significan en las expresiones regulares (es decir, ?requiere 0 o 1 y *requiere 0 o más)? Si es así, ¿ +funciona también?
Dolan Antenucci
37
@dolan: Sí, también +funciona. Ver docs.python.org/2/library/argparse.html#nargs para más detalles.
Vinay Sajip
2
¿hay alguna manera de hacer que dir aparezca en argumentos opcionales? o parece que los argumentos posicionales deberían tener un calificador 'opcional' anterior. ¿es posible registrarlo (en lo que respecta a la ayuda) como tal?
scagnetti
66
@ant De lo anterior, puede ver que dir es opcional (que aparece entre corchetes en la salida de argparse indica esto).
Vinay Sajip
1
Tx! Dir acceso desde options.dir, no args.dir, como estaba intentando!
ptim
69

Como una extensión a la respuesta @VinaySajip. Hay otros que nargsvale la pena mencionar .

  1. parser.add_argument('dir', nargs=1, default=os.getcwd())

N (un entero). N argumentos de la línea de comando se reunirán en una lista

  1. parser.add_argument('dir', nargs='*', default=os.getcwd())

'*'. Todos los argumentos de la línea de comandos presentes se agrupan en una lista. Tenga en cuenta que generalmente no tiene mucho sentido tener más de un argumento posicional con nargs='*', pero nargs='*'es posible tener múltiples argumentos opcionales con .

  1. parser.add_argument('dir', nargs='+', default=os.getcwd())

'+'. Al igual que '*', todos los argumentos de línea de comandos presentes se agrupan en una lista. Además, se generará un mensaje de error si no hubiera al menos un argumento de línea de comando presente.

  1. parser.add_argument('dir', nargs=argparse.REMAINDER, default=os.getcwd())

argparse.REMAINDER. Todos los argumentos restantes de la línea de comandos se agrupan en una lista. Esto suele ser útil para las utilidades de línea de comandos que se envían a otras utilidades de línea de comandos

Si nargsno se proporciona el argumento de la palabra clave, la acción determina el número de argumentos consumidos. En general, esto significa que se consumirá un único argumento de línea de comandos y se generará un único elemento (no una lista).

Editar (copiado de un comentario de @Acumenus) nargs='?' Los documentos dicen: '?'. Si es posible, se consumirá un argumento desde la línea de comando y se generará como un solo elemento. Si no hay ningún argumento de línea de comando, se generará el valor predeterminado.

Matas Vaitkevicius
fuente
3
Cabe señalar, sin embargo, que nargs='?'no produce una lista.
Acumenus
@ABB Última línea de la respuesta Generally this means a single command-line argument will be consumed and a single item (not a list) will be produced.Espero que esto ayude ...
Matas Vaitkevicius
1
La línea citada se refiere al caso de no definir nargs, pero lo nargs='?'está definiendo. Los documentos dicen: '?'. Si es posible, se consumirá un argumento desde la línea de comando y se generará como un solo elemento. Si no hay ningún argumento de línea de comando, se generará el valor predeterminado.
Acumenus
@ABB Solo edita la respuesta si sientes que falta algo. Gracias.
Matas Vaitkevicius
¿Cuál es la diferencia entre nargs=argparse.REMAINDERy nargs='*', como me parece, son idénticos en su efecto (probado en Python 2.7.10 y Python 3.6.1)?
-5

parser.add_argumentTambién tiene un interruptor requerido . Puedes usar required=False. Aquí hay un fragmento de muestra con Python 2.7:

parser = argparse.ArgumentParser(description='get dir')
parser.add_argument('--dir', type=str, help='dir', default=os.getcwd(), required=False)
args = parser.parse_args()
rakhee
fuente
11
OP estaba preguntando acerca de los parámetros posicionales, no '--dir'. 'obligatorio' es un argumento no válido para los posicionales. Y 'falso' era un error tipográfico, se refería a 'Falso'. +1 para novato, -1 para descuidado.
SoloPilot