parser example argumentparser arg_parser add_argument python argparse

python - example - Opción argparse para pasar una lista como opción



python argparse argumentparser() (7)

Estoy intentando pasar una lista como argumento a un programa de línea de comandos. ¿Hay una opción argparse para pasar una lista como opción?

parser.add_argument(''-l'', ''--list'', type=list, action=''store'', dest=''list'', help=''<Required> Set flag'', required=True)

Script se llama como abajo

python test.py -l "265340 268738 270774 270817"


Además de nargs , es posible que desee utilizar choices si conoce la lista de antemano:

>>> parser = argparse.ArgumentParser(prog=''game.py'') >>> parser.add_argument(''move'', choices=[''rock'', ''paper'', ''scissors'']) >>> parser.parse_args([''rock'']) Namespace(move=''rock'') >>> parser.parse_args([''fire'']) usage: game.py [-h] {rock,paper,scissors} game.py: error: argument move: invalid choice: ''fire'' (choose from ''rock'', ''paper'', ''scissors'')


En add_argument() , el type es solo un objeto invocable que recibe una cadena y devuelve el valor de la opción.

import ast def arg_as_list(s): v = ast.literal_eval(s) if type(v) is not list: raise argparse.ArgumentTypeError("Argument /"%s/" is not a list" % (s)) return v def foo(): parser.add_argument("--list", type=arg_as_list, default=[], help="List of values")

Esto permitirá:

$ ./tool --list "[1,2,3,4]"


Prefiero pasar una cadena delimitada que analizo más adelante en el script. Las razones de esto son; la lista puede ser de cualquier tipo int o str , y a veces usando nargs me encuentro con problemas si hay varios argumentos opcionales y argumentos posicionales.

parser = ArgumentParser() parser.add_argument(''-l'', ''--list'', help=''delimited list input'', type=str) args = parser.parse_args() my_list = [int(item) for item in args.list.split('','')]

Entonces,

python test.py -l "265340,268738,270774,270817" [other arguments]

o,

python test.py -l 265340,268738,270774,270817 [other arguments]

funcionará bien El delimitador también puede ser un espacio que, a su vez, impondría comillas alrededor del valor del argumento como en el ejemplo de la pregunta.


Si tiene la intención de hacer que un solo conmutador tome varios parámetros, entonces use nargs=''+'' . Si su ejemplo ''-l'' en realidad está tomando enteros:

a = argparse.ArgumentParser() a.add_argument( ''-l'', ''--list'', # either of this switches nargs=''+'', # one or more parameters to this switch type=int, # /parameters/ are ints dest=''list'', # store in ''list''. default=[], # since we''re not specifying required. ) print a.parse_args("-l 123 234 345 456".split('' '')) print a.parse_args("-l 123 -l=234 -l345 --list 456".split('' ''))

Produce

Namespace(list=[123, 234, 345, 456]) Namespace(list=[456]) # Attention!

Si especifica el mismo argumento varias veces, la acción predeterminada ( ''store'' ) reemplaza los datos existentes.

La alternativa es usar la acción de append :

a = argparse.ArgumentParser() a.add_argument( ''-l'', ''--list'', # either of this switches type=int, # /parameters/ are ints dest=''list'', # store in ''list''. default=[], # since we''re not specifying required. action=''append'', # add to the list instead of replacing it ) print a.parse_args("-l 123 -l=234 -l345 --list 456".split('' ''))

Lo que produce

Namespace(list=[123, 234, 345, 456])

O puede escribir un controlador / acción personalizado para analizar los valores separados por comas para que pueda hacer

-l 123,234,345 -l 456


Tal vez la respuesta más simple

import argparse parser = argparse.ArgumentParser() parser.add_argument("-l", "--tolist", help="input to list", action="store_true") parser.add_argument("newlist", type=str, help="generate a list") args = parser.parse_args() if args.tolist: print(args.newlist.split(" "))


Usando el parámetro nargs en el método add_argument de argparse

Yo uso nargs = '' '' como un parámetro add_argument. Específicamente utilicé nargs = '' '' a la opción para elegir los valores predeterminados si no estoy pasando ningún argumento explícito

Incluyendo un fragmento de código como ejemplo:

Ejemplo: temp_args1.py

Tenga en cuenta: El código de ejemplo siguiente está escrito en python3. Al cambiar el formato de la declaración de impresión, se puede ejecutar en python2

#!/usr/local/bin/python3.6 from argparse import ArgumentParser description = ''testing for passing multiple arguments and to get list of args'' parser = ArgumentParser(description=description) parser.add_argument(''-i'', ''--item'', action=''store'', dest=''alist'', type=str, nargs=''*'', default=[''item1'', ''item2'', ''item3''], help="Examples: -i item1 item2, -i item3") opts = parser.parse_args() print("List of items: {}".format(opts.alist))

Nota: Estoy recopilando varios argumentos de cadena que se almacenan en la lista - opts.alist Si desea una lista de enteros, cambie el parámetro de tipo en parser.add_argument a int

Resultado de la ejecución:

python3.6 temp_agrs1.py -i item5 item6 item7 List of items: [''item5'', ''item6'', ''item7''] python3.6 temp_agrs1.py -i item10 List of items: [''item10''] python3.6 temp_agrs1.py List of items: [''item1'', ''item2'', ''item3'']


TL; DR

Use la opción nargs o la configuración ''append'' de la opción de action (dependiendo de cómo desea que se comporte la interfaz de usuario).

nargs

parser.add_argument(''-l'',''--list'', nargs=''+'', help=''<Required> Set flag'', required=True) # Use like: # python arg.py -l 1234 2345 3456 4567

nargs=''+'' toma 1 o más argumentos, nargs=''*'' toma cero o más.

adjuntar

parser.add_argument(''-l'',''--list'', action=''append'', help=''<Required> Set flag'', required=True) # Use like: # python arg.py -l 1234 -l 2345 -l 3456 -l 4567

Con el append usted proporciona la opción varias veces para construir la lista.

No uses type=list !!! - Probablemente no haya ninguna situación en la que desee utilizar type=list con argparse . Siempre.

Veamos con más detalle algunas de las diferentes maneras en que uno podría intentar hacer esto y el resultado final.

import argparse parser = argparse.ArgumentParser() # By default it will fail with multiple arguments. parser.add_argument(''--default'') # Telling the type to be a list will also fail for multiple arguments, # but give incorrect results for a single argument. parser.add_argument(''--list-type'', type=list) # This will allow you to provide multiple arguments, but you will get # a list of lists which is not desired. parser.add_argument(''--list-type-nargs'', type=list, nargs=''+'') # This is the correct way to handle accepting multiple arguments. # ''+'' == 1 or more. # ''*'' == 0 or more. # ''?'' == 0 or 1. # An int is an explicit number of arguments to accept. parser.add_argument(''--nargs'', nargs=''+'') # To make the input integers parser.add_argument(''--nargs-int-type'', nargs=''+'', type=int) # An alternate way to accept multiple inputs, but you must # provide the flag once per input. Of course, you can use # type=int here if you want. parser.add_argument(''--append-action'', action=''append'') # To show the results of the given option to screen. for _, value in parser.parse_args()._get_kwargs(): if value is not None: print(value)

Aquí está la salida que puede esperar:

$ python arg.py --default 1234 2345 3456 4567 ... arg.py: error: unrecognized arguments: 2345 3456 4567 $ python arg.py --list-type 1234 2345 3456 4567 ... arg.py: error: unrecognized arguments: 2345 3456 4567 $ # Quotes won''t help here... $ python arg.py --list-type "1234 2345 3456 4567" [''1'', ''2'', ''3'', ''4'', '' '', ''2'', ''3'', ''4'', ''5'', '' '', ''3'', ''4'', ''5'', ''6'', '' '', ''4'', ''5'', ''6'', ''7''] $ python arg.py --list-type-nargs 1234 2345 3456 4567 [[''1'', ''2'', ''3'', ''4''], [''2'', ''3'', ''4'', ''5''], [''3'', ''4'', ''5'', ''6''], [''4'', ''5'', ''6'', ''7'']] $ python arg.py --nargs 1234 2345 3456 4567 [''1234'', ''2345'', ''3456'', ''4567''] $ python arg.py --nargs-int-type 1234 2345 3456 4567 [1234, 2345, 3456, 4567] $ # Negative numbers are handled perfectly fine out of the box. $ python arg.py --nargs-int-type -1234 2345 -3456 4567 [-1234, 2345, -3456, 4567] $ python arg.py --append-action 1234 --append-action 2345 --append-action 3456 --append-action 4567 [''1234'', ''2345'', ''3456'', ''4567'']

Para llevar :

  • Use nargs o action=''append''
    • nargs puede ser más directo desde la perspectiva del usuario, pero puede ser poco intuitivo si hay argumentos posicionales porque argparse no puede decir qué debe ser un argumento posicional y qué pertenece a los nargs ; Si tiene argumentos posicionales, action=''append'' puede terminar siendo una mejor opción.
    • Lo anterior solo es cierto si a nargs se le da ''*'' , ''+'' o ''?'' . Si proporciona un número entero (como 4 ), no habrá problemas para mezclar las opciones con nargs y argumentos posicionales porque argparse sabrá exactamente cuántos valores puede esperar de la opción.
  • No use comillas en la línea de comando 1
  • No use type=list , ya que devolverá una lista de listas
    • Esto sucede porque bajo el capó argparse utiliza el valor de type para forzar a cada argumento individual dado su type elegido, no la suma de todos los argumentos.
    • Puedes usar type=int (o lo que sea) para obtener una lista de entradas (o lo que sea)

1 : No quiero decir en general ... Me refiero a que usar comillas para pasar una lista a argparse no es lo que desea.