проанализировать параметры "стиля монтирования" с помощью argparse - PullRequest
1 голос
/ 13 июля 2020

Каков наилучший вариант для анализа параметров «стиля монтирования» в python?

Мне нужно проанализировать argument=value списки, связанные с заданным аргументом c, как в следующем примере:

myprogram --database type=mysql,user=root,passwd=secret,database=mydb --mail type=imap,server=imap.my.domain,user=myself,passwd=othersecret,port=999 --whatever key=val,key=val2,etcetera

Сначала я хотел бы указать один аргумент, а затем проанализировать его вручную (код только для примера):

from argparse import ArgumentParser

parser = ArgumentParser(description='Example only')
parser.add_argument('-D', '--database', nargs=1)
parser.add_argument('-M', '--mail', nargs=1)
parser.add_argument('-W', '--whatever', nargs=1)

args = parser.parse_args('--database type=mysql,user=root,passwd=secret,database=mydb --mail type=imap,server=imap.my.domain,user=myself,passwd=othersecret,port=999 --whatever key=val,key=val2,etcetera'.split())

def parse(a):
    d = {}
    for x in a.split(','):
        try:
            k, v = x.split('=')
        except ValueError:
            k = x
            v = None
        d[k] = v
    
args.database = parse(args.database)
args.mail = parse(args.mail)
args.whatever = parse(args.whatever)

... но мне интересно, есть ли лучший способ.

1 Ответ

0 голосов
/ 14 июля 2020

Оказывается, правильный способ справиться с этим - реализовать собственный argparse.Action.

В конкретном случае c это что-то работает разумно:

!/bin/env python3

from argparse import ArgumentParser, Action


class KeypairAction(Action):
    def __init__(self, option_strings, dest, keys=None, **kwargs):
        super().__init__(option_strings, dest, **kwargs)
        if keys is None:
            raise ValueError('must define "keys" argument')
        if isinstance(keys, dict):
            self.keys = keys
        elif isinstance(keys, (list, tuple)):
            self.keys = {}
            for k in keys:
                if isinstance(k, tuple):
                    k, v = k
                else:
                    v = None
                self.keys[k] = v

    def __call__(self, parser, namespace, values, option_string=None):
        d = {}
        for x in values.split(','):
            try:
                k, v = x.split('=')
            except ValueError:
                k = x
                v = None
            d[k] = v
        setattr(namespace, self.dest, d)


ap = ArgumentParser(description="My nice program")
ap.add_argument('-D', '--database', action=KeypairAction, keys=('type', 'host', 'port', 'user', 'pass', 'db'))
ap.add_argument('-M', '--mail', action=KeypairAction, keys=('type', 'host', 'port', 'user', 'pass'))
ap.add_argument('-W', '--whatever', action=KeypairAction, keys=('key1', 'key2', 'key3', 'etcetera'))

args = ap.parse_args('--database type=mysql,user=root,pass=secret,db=mydb '
                         '--mail type=imap,host=imap.my.domain,user=myself,pass=othersecret,port=999 '
                         '--whatever key1=val,key2=val2,etcetera'.split())
print(args)

Это может быть тривиально расширен для обработки значений по умолчанию.

...