Python argparse: Force a list item to be unique

北慕城南 提交于 2019-12-02 01:11:32

问题


Being able to validate the list items using choices=servers below is nice.

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')

Is it possible to force an item in the list to be unique, so that no duplicates are allowed?


回答1:


The way to properly discard duplicates using argparse would be to create your own argparse.Action class that takes care of using set as suggestted by other answers:

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()

Example output:

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



回答2:


I don't think, that you can enforce this with argparse, but I also don't see any reason to do so. Just document in help that duplicates are ignored. If the user passes duplicate arguments to --only, just let her do so, and ignore the duplicate argument when processing the option arguments (e.g. by turing the list into a set() before processing).




回答3:


Modifying Michel's answer:

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]

Much shorter.




回答4:


Here's an excerpt from some code that I use for a similar purpose:

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')

This is similar in spirit to jcollado's reply, with a modest improvement: multiple options can be specified, with comma separated values, and they are deduped (via set) across all options.

For example:

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

Note that there are two -g args. BRCA2 is specified twice in the first, but appears only once. BRCA1 is specified in the first and second -g opts, but also appears only once.



来源:https://stackoverflow.com/questions/9376670/python-argparse-force-a-list-item-to-be-unique

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!