the parser following error argumentparser argument are python argparse multiple-arguments

parser - Usar la misma opción varias veces en argparse de Python



python argparse argumentparser() (3)

Intento escribir un script que acepte varias fuentes de entrada y haga algo para cada una. Algo como esto

./my_script.py / -i input1_url input1_name input1_other_var / -i input2_url input2_name input2_other_var / -i input3_url input3_name # notice inputX_other_var is optional

Pero no puedo entender cómo hacer esto usando argparse . Parece que está configurado para que cada indicador de opción solo se pueda usar una vez. Sé cómo asociar múltiples argumentos con una sola opción ( nargs=''*'' o nargs=''+'' ), pero eso no me deja usar la bandera -i varias veces. ¿Cómo hago para lograr esto?

Para que quede claro, lo que al final me gustaría es una lista de cadenas de caracteres. Asi que

[["input1_url", "input1_name", "input1_other"], ["input2_url", "input2_name", "input2_other"], ["input3_url", "input3_name"]]


Aquí hay un analizador que maneja un argumento repetido de 2 opcional, con nombres definidos en el metavar :

parser=argparse.ArgumentParser() parser.add_argument(''-i'',''--input'',action=''append'',nargs=2, metavar=(''url'',''name''),help=''help:'') In [295]: parser.print_help() usage: ipython2.7 [-h] [-i url name] optional arguments: -h, --help show this help message and exit -i url name, --input url name help: In [296]: parser.parse_args(''-i one two -i three four''.split()) Out[296]: Namespace(input=[[''one'', ''two''], [''three'', ''four'']])

Esto no maneja el 2 or 3 argument (aunque escribí un parche hace algún tiempo para un error / problema de Python que manejaría dicho rango).

¿Qué tal una definición de argumento por separado con nargs=3 y metavar=(''url'',''name'',''other'') ?

El metavar tupla también se puede usar con nargs=''+'' y nargs=''*'' ; las 2 cuerdas se usan como [-u A [B ...]] o [-u [A [B ...]]] .


Esto es simple; simplemente agregue both action=''append'' y nargs=''*'' (o ''+'' ).

import argparse parser = argparse.ArgumentParser() parser.add_argument(''-i'', action=''append'', nargs=''+'') args = parser.parse_args()

Luego, cuando lo ejecutas, obtienes

In [32]: run test.py -i input1_url input1_name input1_other_var -i input2_url i ...: nput2_name input2_other_var -i input3_url input3_name In [33]: args.i Out[33]: [[''input1_url'', ''input1_name'', ''input1_other_var''], [''input2_url'', ''input2_name'', ''input2_other_var''], [''input3_url'', ''input3_name'']]


-i debe configurarse para aceptar 3 argumentos y para usar la acción de append .

>>> p = argparse.ArgumentParser() >>> p.add_argument("-i", nargs=3, action=''append'') _AppendAction(...) >>> p.parse_args("-i a b c -i d e f -i g h i".split()) Namespace(i=[[''a'', ''b'', ''c''], [''d'', ''e'', ''f''], [''g'', ''h'', ''i'']])

Para manejar un valor opcional, puede intentar usar un tipo personalizado simple. En este caso, el argumento para -i es una cadena delimitada por comas, con el número de divisiones limitado a 2. Necesitaría postprocesar los valores para asegurarse de que hay al menos dos valores especificados.

>>> p.add_argument("-i", type=lambda x: x.split(",", 2), action=''append'') >>> print p.parse_args("-i a,b,c -i d,e -i g,h,i,j".split()) Namespace(i=[[''a'', ''b'', ''c''], [''d'', ''e''], [''g'', ''h'', ''i,j'']])

Para obtener más control, defina una acción personalizada. Este amplía la _AppendAction (usada por action=''append'' ), pero solo hace un cierto rango verificando la cantidad de argumentos dados a -i .

class TwoOrThree(argparse._AppendAction): def __call__(self, parser, namespace, values, option_string=None): if not (2 <= len(values) <= 3): raise argparse.ArgumentError(self, "%s takes 2 or 3 values, %d given" % (option_string, len(values))) super(TwoOrThree, self).__call__(parser, namespace, values, option_string) p.add_argument("-i", nargs=''+'', action=TwoOrThree)