TL; DR
Use la nargs
opción o la 'append'
configuración de la action
opción (dependiendo de 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 construir la lista.
¡No lo uses type=list
! - Probablemente no hay situación en la que se desea utilizar type=list
con argparse
. Siempre.
Echemos un vistazo con más detalle a algunas de las diferentes formas 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']
Comida para llevar :
- Use
nargs
oaction='append'
nargs
puede ser más directo desde la perspectiva del usuario, pero puede no ser 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, action='append'
puede terminar siendo una mejor opción.
- Lo anterior sólo es cierto si
nargs
se da '*'
, '+'
o '?'
. Si proporciona un número entero (como 4
), no habrá problemas para mezclar opciones nargs
y argumentos posicionales porque argparse
sabrá 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 debajo del capó
argparse
usa el valor de type
para coaccionar cada argumento dado individual que haya elegido 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.
type=list
opción. No uses eso. Eso convierte una cadena en una lista y, por lo tanto, las listas de listas.type
parámetro en algún otro objeto. Por defecto, este método devuelve una lista de cadenas.--
podría dividir opciones frente a argumentos posicionales.prog --opt1 par1 ... -- posp1 posp2 ...
--
ayuda a resolver esto como se muestra en el ejemplo en mi comentario anterior. Suministros de usuario IOW--
seguidos de todos los argumentos posicionales.Prefiero pasar una cadena delimitada que analizo más adelante en el script. Las razones para esto son; la lista puede ser de cualquier tipo
int
ostr
, y a veces usandonargs
me encuentro con problemas si hay múltiples argumentos opcionales y argumentos posicionales.Entonces,
o,
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.
fuente
type
argumento enlambda s: [int(time) for item in s.split(',')]
lugar de postprocesamientoargs.list
.int(time)
debería serloint(item)
. Mi ejemplo fue una versión simplificada de lo que normalmente hago, donde verifico muchas otras cosas en lugar de un simple procesamiento. Pero simplemente para responder a la pregunta, yo también encuentro tu camino más elegante ..lambda items: list(csv.reader([items]))[0]
con la biblioteca csv estándar hay una versión modificada del comentario de @chepner para cualquier persona preocupada por la entrada arbitraria de CSV (ref: respuesta de @adamk ).Además
nargs
, es posible que desee utilizarchoices
si conoce la lista de antemano:fuente
Usar el parámetro nargs en el método add_argument de argparse
Yo uso nargs = ' ' como un parámetro add_argument. Usé específicamente nargs = ' ' para la opción de elegir 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 siguiente código de muestra está escrito en python3. Al cambiar el formato de la declaración de impresión, puede ejecutarse en python2
Nota: estoy recopilando múltiples 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:
fuente
temp_args1.py -i [item5 ,item6, item7]
y que la salida salga también como una lista (en lugar de una lista anidada)Si tiene la intención de hacer que un solo interruptor tome múltiples parámetros, entonces los usa
nargs='+'
. Si su ejemplo '-l' en realidad está tomando enteros:Produce
Si especifica el mismo argumento varias veces, la acción predeterminada (
'store'
) reemplaza los datos existentes.La alternativa es usar la
append
acción:Que produce
O puede escribir un controlador / acción personalizado para analizar valores separados por comas para que pueda hacer
fuente
En
add_argument()
,type
es solo un objeto invocable que recibe una cadena y devuelve el valor de la opción.Esto permitirá:
fuente
Si tiene una lista anidada donde las listas internas tienen diferentes tipos y longitudes y desea conservar el tipo, por ejemplo,
[[1, 2], ["foo", "bar"], [3.14, "baz", 20]]
entonces puede usar la solución propuesta por @ sam-mason para esta pregunta , que se muestra a continuación:
lo que da:
fuente
Quiero manejar pasar múltiples listas, valores enteros y cadenas.
Enlace útil => ¿Cómo pasar una variable Bash a Python?
El orden no es importante. Si desea pasar una lista acaba de hacer como en el medio
"["
y"]
y separarlos mediante una coma.Entonces,
Salida =>
['my_string', '3', ['1', '2'], ['3', '4', '5']]
, lamy_args
variable contiene los argumentos en orden.fuente
Creo que la solución más elegante es pasar una función lambda a "tipo", como lo menciona Chepner. Además de esto, si no sabe de antemano cuál será el delimitador de su lista, también puede pasar varios delimitadores para re.split:
fuente
-l
en la llamada de ejemplo? ¿De donde-n
vino?parser.add_argument('-l', '--list', type = lambda s: re.split('[ ,;]', s))
. Aquí está la entrada:script.py -l abc xyz, abc\nxyz
. Finalmente, aquí está el resultado:script.py: error: unrecognized arguments: xyz, abcnxyz