Python argparse: obliga a un elemento de la lista a ser único

Ser capaz de validar los elementos de la lista usando las choices=servers continuación es bueno.

 servers = [ "ApaServer", "BananServer", "GulServer", "SolServer", "RymdServer", "SkeppServer", "HavsServer", "SovServer" ] parser = argparse.ArgumentParser() parser.add_argument('-o', '--only', nargs='*', choices=servers, help='Space separated list of case sensitive server names to process') 

¿Es posible forzar que un elemento de la lista sea único, de modo que no se permitan duplicados?

La forma de descartar correctamente los duplicados utilizando argparse sería crear su propia clase argparse.Action que se encargue de usar el set como lo sugieren otras respuestas:

 import argparse class UniqueAppendAction(argparse.Action): def __call__(self, parser, namespace, values, option_string=None): unique_values = set(values) setattr(namespace, self.dest, unique_values) servers = ["ApaServer", "BananServer", "GulServer", "SolServer", "RymdServer", "SkeppServer", "HavsServer", "SovServer" ] parser = argparse.ArgumentParser() parser.add_argument('-o', '--only', nargs='*', choices=servers, action=UniqueAppendAction, help='Space separated list of case sensitive server names to process') print parser.parse_args() 

Ejemplo de salida:

 $ python test.py -o ApaServer ApaServer Namespace(only=set(['ApaServer'])) 

No creo que puedas hacer esto con argparse , pero tampoco veo ninguna razón para hacerlo. Solo documente en la help que se ignoran los duplicados. Si el usuario pasa argumentos duplicados a --only , simplemente permítale que lo haga, e ignore el argumento duplicado al procesar los argumentos de opción (por ejemplo, convirtiendo la lista en un set() antes de procesar).

Modificando la respuesta de Michel:

 In [1]: x = [5,6,5] In [2]: x_nodups = list(set(x)) In [3]: x_nodups Out[3]: [5, 6] In [4]: x_nodups_michel = dict(map(lambda i: (i,1),x)).keys() In [5]: x_nodups_michel Out[5]: [5, 6] 

Mucho más corto.

Aquí hay un extracto de un código que uso para un propósito similar:

 def parse_args(argv): class SetAction(argparse.Action): """argparse.Action subclass to store distinct values""" def __call__(self, parser, namespace, values, option_string=None): try: getattr(namespace,self.dest).update( values ) except AttributeError: setattr(namespace,self.dest,set(values)) ap = argparse.ArgumentParser( description = __doc__, formatter_class = argparse.ArgumentDefaultsHelpFormatter, ) ap.add_argument('--genes', '-g', type = lambda v: v.split(','), action = SetAction, help = 'select by specified gene') 

Esto es similar en espíritu a la respuesta de jcollado, con una mejora modesta: se pueden especificar múltiples opciones, con valores separados por comas, y se deducen (a través del conjunto) en todas las opciones.

Por ejemplo:

 snafu$ ./bin/ucsc-bed -g BRCA1,BRCA2,DMD,TNFA,BRCA2 -g BRCA1 Namespace(genes=set([u'BRCA1', u'BRCA2', u'DMD', u'TNFA'])) 

Tenga en cuenta que hay dos argumentos -g. BRCA2 se especifica dos veces en el primero, pero aparece solo una vez. BRCA1 se especifica en la primera y la segunda opción -g, pero también aparece solo una vez.