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
oaction=''append''
-
nargs
puede ser más directo desde la perspectiva del usuario, pero puede ser poco intuitivo si hay argumentos posicionales porqueargparse
no puede decir qué debe ser un argumento posicional y qué pertenece a losnargs
; 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 (como4
), no habrá problemas para mezclar las opciones connargs
y argumentos posicionales porqueargparse
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 detype
para forzar a cada argumento individual dado sutype
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)
- Esto sucede porque bajo el capó
1 : No quiero decir en general ... Me refiero a que usar comillas para pasar una lista a argparse
no es lo que desea.