argparse: создание списка dict из аргументов CLI? - PullRequest
0 голосов
/ 27 февраля 2020

Разработка иерархической программы CLI. Что-то вроде:

$ python -m foo -'{' -c 'wow' -b 'has' -d 55 -'}' \
                -'{' -c 'haz' -b 'wow' -'}' \
                -'{' -d 56 -'}'

Что я хотел бы return:

[
    { 'c': 'wow', 'b': 'has', 'd': 55 },
    { 'c': 'haz', 'b': 'wow' },
    { 'd': 56 }
]

Основной вопрос: как мне построить это в argparse, т.е. без отдельной функции, которая запускается после vars(parser.parse_args())?

Вспомогательный вопрос: строит ли иерархии, подобные этой, в интерфейсе CLI, т. е. не во внешнем файле json или как type=yaml.loads, но как должный Свойство / значения CLI нарушают какое-то соглашение, что должно заставить меня пересмотреть этот дизайн?

PS: я могу создать это просто без argparse, используя sys.argv, один дополнительный list и область видимости скаляр. Но argparse даст мне авто-помощь, автозаполнение, значения по умолчанию, безопасность типов и многое другое ... поэтому предпочел бы использовать его.

РЕДАКТИРОВАТЬ: sys.argv[1:] пример:

[ '-m', 'foo', '-{', '-c', 'wow', '-b', 'has', '-d', '55', '-}',
  '-{', '-c', 'haz', '-b', 'wow', '-}', '-{', '-d', '56', '-}' ]

Ответы [ 2 ]

1 голос
/ 27 февраля 2020

Я думаю, что существует слабое «соглашение» о том, что аргументы CLI должны быть достаточно простыми; как только вы начнете помещать данные о серьезных количествах в командную строку, тогда, возможно, вам следует пересмотреть свой дизайн. В конце концов, файлы предназначены для хранения данных.

0 голосов
/ 28 февраля 2020

Создана базовая c версия, работающая только с одним уровнем иерархии:

Программа

from argparse import ArgumentParser, ArgumentTypeError
from sys import argv
from pprint import pprint


def build_parser():
    parser = ArgumentParser(prog='python -m foo', description='.')
    parser.add_argument('-c')
    parser.add_argument('-b')
    parser.add_argument('-d', type=int)
    return parser


def main():
    level, working, whole = 0, [], []
    for arg in argv[1:]:
        if arg == '-{':
            level += 1
        elif arg == '-}':
            whole.append(tuple(working))
            working.clear()
            level -= 1
        else:
            working.append(arg)
    if level & 1 != 0:
        raise ArgumentTypeError('Imbalanced {}')
    parser = build_parser()

    return tuple(map(lambda args: parser.parse_args(args), whole))
    # For list of dicts, modify ^ vars(parser.parse_args(args))


if __name__ == '__main__':
    pprint(main(), indent=4)

I / O

$ python -m foo -'{' -c 'wow' -b 'has' -d 55 -'}' \
                -'{' -c 'haz' -b 'wow' -'}' \
                -'{' -d 56 -'}'
(   Namespace(b='has', c='wow', d=55),
    Namespace(b='wow', c='haz', d=None),
    Namespace(b=None, c=None, d=56))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...