Python argparse dict arg

Я хочу получить аргумент dict(str -> str) из командной строки. Предоставляет ли argparse.ArgumentParser его? Или любая другая библиотека?

Для командной строки:

program.py --dict d --key key1 --value val1 --key key2 --value val2

Я ожидаю следующий словарь:

d = {"key1": "val1", "key2": "val2"}

Ответ 1

Здесь другое решение, использующее пользовательское действие, если вы хотите указать пары ключей dict вместе через запятую -

import argparse
import sys
parser = argparse.ArgumentParser(description='parse key pairs into a dictionary')

class StoreDictKeyPair(argparse.Action):
     def __call__(self, parser, namespace, values, option_string=None):
         my_dict = {}
         for kv in values.split(","):
             k,v = kv.split("=")
             my_dict[k] = v
         setattr(namespace, self.dest, my_dict)

parser.add_argument("--key_pairs", dest="my_dict", action=StoreDictKeyPair, metavar="KEY1=VAL1,KEY2=VAL2...")

args = parser.parse_args(sys.argv[1:])
print args

Бег:

python parse_kv.py --key_pairs 1=2,a=bbb,c=4 --key_pairs test=7,foo=bar

Выход:

Namespace(my_dict={'1': '2', 'a': 'bbb', 'c': '4', 'test': '7', 'foo': 'bar'})

Если вы хотите использовать nargs вместо значений через запятую в строке:

class StoreDictKeyPair(argparse.Action):
     def __init__(self, option_strings, dest, nargs=None, **kwargs):
         self._nargs = nargs
         super(StoreDictKeyPair, self).__init__(option_strings, dest, nargs=nargs, **kwargs)
     def __call__(self, parser, namespace, values, option_string=None):
         my_dict = {}
         print "values: {}".format(values)
         for kv in values:
             k,v = kv.split("=")
             my_dict[k] = v
         setattr(namespace, self.dest, my_dict)

parser.add_argument("--key_pairs", dest="my_dict", action=StoreDictKeyPair, nargs="+", metavar="KEY=VAL")

args = parser.parse_args(sys.argv[1:])
print args

Бег

python arg_test4.py --key_pairs 1=2 a=bbb c=4 test=7 foo=bar

Выходы:

values: ['1=2', 'a=bbb', 'c=4', 'test=7', 'foo=bar']
Namespace(my_dict={'1': '2', 'a': 'bbb', 'c': '4', 'test': '7', 'foo': 'bar'})

Ответ 2

Я бы использовал что-то вроде этого:

p = argparse.ArgumentParser()
p.add_argument("--keyvalue", action='append',
               type=lambda kv: kv.split("="), dest='keyvalues')

args = p.parse_args("--keyvalue foo=6 --keyvalue bar=baz".split())
d = dict(args.keyvalues)

Вы можете создать настраиваемое действие, которое "добавляет" пар синтаксического анализа непосредственно в словарь, а не просто накапливает список кортежей (key, value). (Что я вижу, это то, что сделал skyline75489, мой ответ отличается использованием одного параметра --keyvalue с настраиваемым типом вместо отдельных опций --key и --value для указания пар.)

Ответ 3

Python получает аргументы в виде массива argv. Вы можете использовать это для создания словаря в самой программе.

import sys
my_dict = {}
for arg in sys.argv[1:]:
    key, val=arg.split(':')[0], arg.split(':')[1]
    my_dict[key]=val

print my_dict

Для командной строки:

python program.py key1:val1 key2:val2 key3:val3

Вывод:

my_dict = {'key3': 'val3', 'key2': 'val2', 'key1': 'val1'}

Примечание: args будет в строке, поэтому вам придется преобразовать их для хранения числовых значений.

Надеюсь, это поможет.

Ответ 4

просто еще один простой способ:

parser = argparse.ArgumentParser()
parser.add_argument('--key1')
parser.add_argument('--key2')
args = parser.parse_args()
my_dict = args.__dict__

Ответ 5

Аргументы словаря аргументов в строке строки Python argparse_dictionary.py

# $ python argparse_dictionary.py --arg_dict=1=11,2=22;3=33 --arg_dict=a=,b,c=cc,=dd,=ee=,
# Namespace(arg_dict={'1': '11', '2': '22', '3': '33', 'a': '', 'c': 'cc', '': 'dd'})

import argparse

arg_parser = argparse.ArgumentParser()
arg_parser.add_argument('--arg_dict', action=type(b'', (argparse.Action,), dict(__call__=lambda self, parser, namespace, values, option_string: getattr(namespace, self.dest).update(dict([v.split('=') for v in values.replace(';', ',').split(',') if len(v.split('=')) == 2])))), default={}, metavar='KEY1=VAL1,KEY2=VAL2;KEY3=VAL3...')
print(arg_parser.parse_args())

Ответ 6

Прямой способ анализа синтаксического ввода:

program.py --dict d --key key1 --value val1 --key key2 --value val2

:

parser=argparse.ArgumentParser()
parser.add_argument('--dict')
parser.add_argument('--key', action='append')
parser.add_argument('--value', action='append')
args = parser.parse_args()

который должен произвести (если мой психический парсер правильно)

args = Namespace(dict='d', key=['key1','key2'], value=['value1','value2'])

Вы должны иметь возможность построить словарь из этого:

adict = {k:v for k, v in zip(args.key, args.value)}

Использование args.dict для назначения этого переменной с этим именем требует некоторой обманчивости не-питона. Лучше всего было бы создать элемент в другом словаре с этим именем.

another_dict = {args.dict: adict}

Это решение не выполняет большую проверку ошибок. Например, он не гарантирует, что имеется одинаковое количество ключей и значений. Это также не позволит вам создать несколько словарей (т.е. Повторить аргументы --dict). Это не требует особого порядка. --dict может возникнуть после пары --key key1. Несколько аргументов --value могут быть вместе.

Связывание key=value вместе как chepner происходит вокруг ряда этих проблем.

Ответ 7

В Python 3.6 есть простое решение, если вы просто пытаетесь преобразовать argparse-ввод в словарь. Пример таков:

import argparse 

parser = argparse.ArgumentParser()
parser.add_argument('-i', '--input', help='the path to the input file')
parser.add_argument('-o', '--output', help='the path to the output file')
args = parser.parse_args()

arguments = dict(args._get_kwargs())

for k, v in arguments.items():
    print(k, v) 

При заданном вводе командной строки, таком как python3 script_name.py --input 'input.txt' --output 'output.txt' код будет выводиться на терминал:

input input.txt
output output.txt

Ответ 8

Что касается текущих библиотек, таких как argparse, docopt и нажмите, ни одна из них не поддерживает использование аргументов dict. Лучшее решение, о котором я могу думать, - создать пользовательский argparse.Action, чтобы поддерживать его самостоятельно:

import argparse

class MyAction(argparse.Action):
    def __init__(self, option_strings, dest, nargs=None, **kwargs):
        super(MyAction, self).__init__(option_strings, dest, nargs, **kwargs)

    def __call__(self, parser, namespace, values, option_string=None):
        print '%r %r %r' % (namespace, values, option_string)
        value_dict = {}
        values.reverse()
        while len(values) > 0:
            v = eval(values.pop()).lstrip('--') # This is like crazy hack, I know.
            k = eval(values.pop())
            value_dict[k] = v

        setattr(namespace, self.dest, value_dict)

parser = argparse.ArgumentParser()
parser.add_argument('-d', action=MyAction, nargs='*')
args = parser.parse_args('-d "--key" "key1" "--value" "val1" "--key" "key2" "--value" "val2"'.split())

print(args)