¿Cómo puedo pasar una lista como argumento de línea de comandos con argparse?

505
carte blanche 2013-04-02 13:34.

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

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

El script se llama como a continuación

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

10 answers

1006
SethMMorton 2013-04-02 13:37.

TL; DR

Utilice la nargsopción o la 'append'configuración de la actionopción (según cómo desee 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 appendusted proporciona la opción varias veces para crear la lista.

¡ type=list¡¡ No lo use !!! - Probablemente no hay situación en la que se desea utilizar type=listcon argparse. Alguna vez.


Echemos un vistazo con más detalle a algunas de las diferentes formas en que se puede 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á el resultado 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']

Conclusiones :

  • Utilice nargsoaction='append'
    • nargspuede ser más sencillo desde la perspectiva del usuario, pero puede ser poco intuitivo si hay argumentos posicionales porque argparseno se puede decir qué debería ser un argumento posicional y qué pertenece al nargs; si tiene argumentos posicionales, entonces action='append'puede terminar siendo una mejor opción.
    • Lo anterior sólo es cierto si nargsse da '*', '+'o '?'. Si proporciona un número entero (como 4), no habrá problemas para mezclar opciones con nargsargumentos posicionales porque argparsesabrá exactamente cuántos valores esperar para la opción.
  • No use comillas en la línea de comando 1
  • No lo use type=list, ya que devolverá una lista de listas
    • Esto sucede porque bajo el capó argparseusa el valor de typepara coaccionar a cada argumento individual dado que usted eligió type, no el agregado de todos los argumentos.
    • Puede usar type=int(o lo que sea) para obtener una lista de entradas (o lo que sea)

1 : No me refiero en general ... me refiero a que usar comillas para pasar una listaargparse no es lo que quieres.

93
dojuba 2014-07-22 03:55.

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 into str, y a veces, al usar, nargsme encuentro con problemas si hay múltiples 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, sin embargo, impondría comillas alrededor del valor del argumento como en el ejemplo de la pregunta.

O puede usar un tipo lambda como lo sugiere Chepner en los comentarios:

parser.add_argument('-l', '--list', help='delimited list input', 
    type=lambda s: [int(item) for item in s.split(',')])
19
Martin Thoma 2014-03-28 01:52.

Además nargs, es posible que desee utilizar choicessi 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')
12
Py_minion 2017-01-21 10:30.

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

Yo uso nargs = ' ' como parámetro add_argument. Usé específicamente nargs = ' ' para la opción de elegir valores predeterminados si no paso ningún argumento explícito

Incluyendo un fragmento de código como ejemplo:

Ejemplo: temp_args1.py

Tenga en cuenta: El siguiente código de muestra 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 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']
5
kfsone 2017-04-01 06:45.

Si tiene la intención de hacer que un solo interruptor tome varios parámetros, entonces use nargs='+'. Si su ejemplo '-l' en realidad está tomando números 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 appendacción:

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(' '))

Que produce

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

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

-l 123,234,345 -l 456
5
wonder.mice 2017-11-11 07:04.

En add_argument(), typees 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]"
2
Meysam Sadeghi 2019-07-20 03:14.

Si tiene una lista anidada donde las listas internas tienen diferentes tipos y longitudes y le gustaría conservar el tipo, por ejemplo,

[[1, 2], ["foo", "bar"], [3.14, "baz", 20]]

entonces puede usar la solución propuesta por @ sam-mason a esta pregunta , que se muestra a continuación:

from argparse import ArgumentParser
import json

parser = ArgumentParser()
parser.add_argument('-l', type=json.loads)
parser.parse_args(['-l', '[[1,2],["foo","bar"],[3.14,"baz",20]]'])

lo que da:

Namespace(l=[[1, 2], ['foo', 'bar'], [3.14, 'baz', 20]])
1
Nebulastic 2020-04-15 00:43.

Creo que la solución más elegante es pasar una función lambda a "escribir", como lo menciona Chepner. Además de esto, si no sabes de antemano cuál será el delimitador de tu lista, también puedes pasar múltiples delimitadores a re.split:

# python3 test.py -l "abc xyz, 123"

import re
import argparse

parser = argparse.ArgumentParser(description='Process a list.')
parser.add_argument('-l', '--list',
                    type=lambda s: re.split(' |, ', s),
                    required=True,
                    help='comma or space delimited list of characters')

args = parser.parse_args()
print(args.list)


# Output: ['abc', 'xyz', '123']
0
alper 2020-03-17 07:12.

Quiero manejar el paso de múltiples listas, valores enteros y cadenas.

Enlace útil => ¿Cómo pasar una variable Bash a Python?

def main(args):
    my_args = []
    for arg in args:
        if arg.startswith("[") and arg.endswith("]"):
            arg = arg.replace("[", "").replace("]", "")
            my_args.append(arg.split(","))
        else:
            my_args.append(arg)

    print(my_args)


if __name__ == "__main__":
    import sys
    main(sys.argv[1:])

El orden no es importante. Si desea pasar una lista, haga lo mismo entre "["y "]y sepárelos con una coma.

Entonces,

python test.py my_string 3 "[1,2]" "[3,4,5]"

Salida => ['my_string', '3', ['1', '2'], ['3', '4', '5']], la my_argsvariable contiene los argumentos en orden.

0
Léonard 2020-09-25 20:40.

Puede analizar la lista como una cadena y usar la evalfunción incorporada para leerla como una lista. En este caso, tendrá que poner comillas simples entre comillas dobles (o al revés) para garantizar un análisis de cadenas exitoso.

# declare the list arg as a string
parser.add_argument('-l', '--list', type=str)

# parse
args = parser.parse()

# turn the 'list' string argument into a list object
args.list = eval(args.list)
print(list)
print(type(list))

Pruebas:

python list_arg.py --list "[1, 2, 3]"

[1, 2, 3]
<class 'list'>

Related questions

MORE COOL STUFF

La estrella de HGTV, Christina Hall, revela que tiene 'envenenamiento por mercurio y plomo' probablemente por voltear 'casas asquerosas'

La estrella de HGTV, Christina Hall, revela que tiene 'envenenamiento por mercurio y plomo' probablemente por voltear 'casas asquerosas'

La estrella de HGTV, Christina Hall, revela que le diagnosticaron envenenamiento por mercurio y plomo, probablemente debido a su trabajo como manipuladora de casas.

La estrella de 'Love Is Blind' Brennon Lemieux responde a los cargos de violencia doméstica

La estrella de 'Love Is Blind' Brennon Lemieux responde a los cargos de violencia doméstica

Recientemente salió a la luz un informe policial que acusa a la estrella de 'Love Is Blind', Brennon, de violencia doméstica. Ahora, Brennon ha respondido a los reclamos.

Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia Judd en un momento festivo de pánico

Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia Judd en un momento festivo de pánico

Conozca cómo Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia mientras organizaba la primera celebración de Acción de Gracias desde que murió su madre, Naomi Judd.

Experto en lenguaje corporal explica los 'paralelos' entre Kate Middleton y la princesa Diana

Experto en lenguaje corporal explica los 'paralelos' entre Kate Middleton y la princesa Diana

Descubra por qué un destacado experto en lenguaje corporal cree que es fácil trazar "tales paralelismos" entre la princesa Kate Middleton y la princesa Diana.

Los láseres arrojan luz sobre por qué necesita cerrar la tapa antes de descargar

Los láseres arrojan luz sobre por qué necesita cerrar la tapa antes de descargar

Los inodoros arrojan columnas de aerosol invisibles con cada descarga. ¿Como sabemos? La prueba fue capturada por láseres de alta potencia.

The Secrets of Airline Travel Quiz

The Secrets of Airline Travel Quiz

Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

¿Caduca el repelente de insectos?

¿Caduca el repelente de insectos?

¿Sigue siendo efectivo ese lote de repelente de insectos que te quedó del verano pasado? Si es así, ¿por cuánto tiempo?

Esta mujer murió por el derecho al voto hace 104 años hoy

Esta mujer murió por el derecho al voto hace 104 años hoy

Las mujeres del Reino Unido acuden a las urnas para las elecciones especiales de hoy en un aniversario particularmente apropiado. Han pasado 104 años desde que Emily Wilding Davison murió por la causa del sufragio femenino, pisoteada hasta la muerte en medio de una carrera de caballos de alto perfil, frente al Rey y la Reina.

Ponle una tapa. En realidad, ponle una tapa a todo. Consigue 12 tapas de cocina elásticas de silicona por $14. [Exclusivo]

Ponle una tapa. En realidad, ponle una tapa a todo. Consigue 12 tapas de cocina elásticas de silicona por $14. [Exclusivo]

Tapas elásticas de silicona de Tomorrow's Kitchen, paquete de 12 | $14 | Amazonas | Código promocional 20OFFKINJALids son básicamente los calcetines de la cocina; siempre perdiéndose, dejando contenedores huérfanos que nunca podrán volver a cerrarse. Pero, ¿y si sus tapas pudieran estirarse y adaptarse a todos los recipientes, ollas, sartenes e incluso frutas en rodajas grandes que sobran? Nunca más tendrás que preocuparte por perder esa tapa tan específica.

Cuéntanos tus mejores trucos de Washington, DC

Cuéntanos tus mejores trucos de Washington, DC

Hemos pirateado algunas ciudades industriales en esta columna, como Los Ángeles y Las Vegas. Ahora es el momento de una ciudad militar-industrial-compleja.

Un minorista está eliminando su sección de tallas grandes y mezclando tallas más grandes con todo lo demás

Un minorista está eliminando su sección de tallas grandes y mezclando tallas más grandes con todo lo demás

Un minorista está enlatando su sección de tallas grandes. Pero no están tomando la categoría solo en línea o descontinuándola por completo.

Patinaje artístico de EE. UU. 'frustrado' por falta de decisión final en evento por equipos, pide una decisión justa

Patinaje artístico de EE. UU. 'frustrado' por falta de decisión final en evento por equipos, pide una decisión justa

El equipo está a la espera de las medallas que ganó en los Juegos Olímpicos de Invierno de 2022 en Beijing, ya que se está resolviendo un caso de dopaje que involucra a la patinadora artística rusa Kamila Valieva.

Los compradores de Amazon dicen que duermen 'como un bebé mimado' gracias a estas fundas de almohada de seda que cuestan tan solo $ 10

Los compradores de Amazon dicen que duermen 'como un bebé mimado' gracias a estas fundas de almohada de seda que cuestan tan solo $ 10

Miles de compradores de Amazon recomiendan la funda de almohada de seda Mulberry, y está a la venta en este momento. La funda de almohada de seda viene en varios colores y ayuda a mantener el cabello suave y la piel clara. Compre las fundas de almohada de seda mientras tienen hasta un 46 por ciento de descuento en Amazon

Se busca al corredor de los Bengals Joe Mixon por orden de arresto emitida por presuntamente apuntar con un arma de fuego a una mujer

Se busca al corredor de los Bengals Joe Mixon por orden de arresto emitida por presuntamente apuntar con un arma de fuego a una mujer

El jueves se presentó una denuncia de delito menor amenazante agravado contra Joe Mixon.

Profesor de la Universidad de Purdue arrestado por presuntamente traficar metanfetamina y proponer favores sexuales a mujeres

Profesor de la Universidad de Purdue arrestado por presuntamente traficar metanfetamina y proponer favores sexuales a mujeres

El Departamento de Policía de Lafayette comenzó a investigar a un profesor de la Universidad de Purdue en diciembre después de recibir varias denuncias de un "hombre sospechoso que se acercaba a una mujer".

Concept Drift: el mundo está cambiando demasiado rápido para la IA

Concept Drift: el mundo está cambiando demasiado rápido para la IA

Al igual que el mundo que nos rodea, el lenguaje siempre está cambiando. Mientras que en eras anteriores los cambios en el idioma ocurrían durante años o incluso décadas, ahora pueden ocurrir en cuestión de días o incluso horas.

India me está pateando el culo

India me está pateando el culo

Estoy de vuelta por primera vez en seis años. No puedo decirte cuánto tiempo he estado esperando esto.

ℝ

“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.

¿Merrick Garland le ha fallado a Estados Unidos?

Es más de la mitad de la presidencia de Biden. ¿Qué está esperando Merrick Garland?

¿Merrick Garland le ha fallado a Estados Unidos?

Creo, un poco tarde en la vida, en dar oportunidades a la gente. Generosamente.

Language