Подтвердить что ты не робот

Принятие словаря в качестве аргумента с помощью argparse и python

Я пытаюсь принять аргумент типа = dict с помощью argparse, но независимо от ввода, он дает ошибку недействительного значения dict.

#!/usr/bin/env python

import argparse

MYDICT = {'key': 'value'}

parser = argparse.ArgumentParser()
parser.add_argument("-m", "--mydict", action="store",
                    required=False, type=dict,
                    default=MYDICT)

args = parser.parse_args()

print args.mydict

Это то, что происходит, когда я пытаюсь передать словарь в script

./argp.py -m "{'key1': 'value1'}"
usage: argp.py [-h] [-m MYDICT]
argp.py: error: argument -m/--mydict: invalid dict value: "{'key1': 'value1'}"

Глядя на документы, я думаю, что это будет возможно.

http://docs.python.org/dev/library/argparse.html

"Любой объект, который поддерживает оператор in, может быть передан как значение выбора, поэтому все объекты dict, заданные объекты, пользовательские контейнеры и т.д. поддерживаются".

4b9b3361

Ответ 1

Я не думаю, что можно передать словарь в качестве аргумента в командной строке, потому что не существует функции преобразования из строки в dict ( EDIT: возможен взлом, см. ниже). Что вы, по сути, говорите, что python:

dict("{'key1': 'value1'}")

Что, если вы попробуете его в консоли python, не работает.

Какая фраза:

"Любой объект, который поддерживает оператор in, может быть передан как значение выбора, поэтому все объекты dict, заданные объекты, пользовательские контейнеры и т.д. поддерживаются".

относится к аргументу choice, который может быть передан с помощью функции add_argument - не для аргумента типа.

Лучше всего, вероятно, принять ваш аргумент как строку, а затем преобразовать его с помощью json возможностей python:

parser.add_argument('-m', '--my-dict', type=str)
args = parser.parse_args()

import json
my_dictionary = json.loads(args.my_dict)

Затем вы можете передать словарь в виде строки. Вы можете попробовать json encoder/decoder для себя в консоли python, чтобы узнать, как это работает:

>>>json.loads('{"value1":"key1"}')
{u'value1': u'key1'}

EDIT: hpaulj указал мне, что вы можете "взломать" параметр типа, передав его json.loads.

import json
parser.add_argument('-d', '--my-dict', type=json.loads)
args = parse.parse_args()

mydict = args.my_dict  # Will return a dictionary

Причина, по которой это работает, на самом деле довольно интересна, потому что внутренне argparse будет просто использовать значение параметра как функцию для преобразования аргумента. т.е. если type = int, то он будет использовать int (arg) или if type = json.loads, тогда json.loads(arg)

Это также означает, что вы можете передать любую функцию, которая принимает один параметр в качестве аргумента для ввода и выполнения пользовательских преобразований, если вам нужно:)