Estoy intentando pasar una lista como argumento a un programa de línea de comandos. ¿Existe una argparse
opció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"
TL; DR
Utilice la nargs
opción o la 'append'
configuración de la action
opció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 append
usted 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=list
con 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 :
nargs
oaction='append'
nargs
puede ser más sencillo desde la perspectiva del usuario, pero puede ser poco intuitivo si hay argumentos posicionales porque argparse
no 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.nargs
se da '*'
, '+'
o '?'
. Si proporciona un número entero (como 4
), no habrá problemas para mezclar opciones con nargs
argumentos posicionales porque argparse
sabrá exactamente cuántos valores esperar para la opción.type=list
, ya que devolverá una lista de listas
argparse
usa el valor de type
para coaccionar a cada argumento individual dado que usted eligió type
, no el agregado de todos los argumentos.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.
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, al usar, nargs
me 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(',')])
Además 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')
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']
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 append
acció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
En add_argument()
, 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]"
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]])
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']
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_args
variable contiene los argumentos en orden.
Puede analizar la lista como una cadena y usar la eval
funció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'>
La estrella de HGTV, Christina Hall, revela que le diagnosticaron envenenamiento por mercurio y plomo, probablemente debido a su trabajo como manipuladora de casas.
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.
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.
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 inodoros arrojan columnas de aerosol invisibles con cada descarga. ¿Como sabemos? La prueba fue capturada por láseres de alta potencia.
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?
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!
¿Sigue siendo efectivo ese lote de repelente de insectos que te quedó del verano pasado? Si es así, ¿por cuánto tiempo?
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.
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.
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á enlatando su sección de tallas grandes. Pero no están tomando la categoría solo en línea o descontinuándola por completo.
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.
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
El jueves se presentó una denuncia de delito menor amenazante agravado contra Joe Mixon.
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".
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.
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.
Creo, un poco tarde en la vida, en dar oportunidades a la gente. Generosamente.