2013-09-04 10 views
20

Próbuję zaakceptować argument type = dict z argparse, ale bez względu na dane wejściowe podaje błąd nieprawidłowej wartości dyktowanej.Akceptowanie słownika jako argumentu z argparse i pythonem

#!/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 

To co się dzieje, gdy próbuję i przekazać słownika do skryptu

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

patrząc na dokumenty to myślę, że byłoby to możliwe.

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

„Każdy obiekt, który obsługuje w operatora mogą być przekazywane jako wartość wyborów, tak DICT przedmiotów, obiektów, niestandardowe zestawy pojemników itp są obsługiwane.”

+0

linii, którą cytat z dokumentacji dotyczy argument słowa kluczowego "wybory", który określa, jakie wartości argumentów są dozwolone. Przekazanie dyktatu do wyboru jest równoznaczne z przekazaniem listy kluczy. Dlatego przekazanie "{" a ": 2," b ": 3}" ograniczyłoby dozwolone argumenty do twojej flagi "--mydict" do "a" lub "b". –

Odpowiedz

26

nie sądzę możliwe jest przekazanie słownika jako argumentu w wierszu poleceń, ponieważ nie istnieje funkcja konwersji z ciągu znaków do dyktowania (EDYCJA: Możliwe jest hakowanie , patrz poniżej). Co to w gruncie mówiąc Pythona zrobić, to:

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

Które jeśli go wypróbować w konsoli Pythona, nie działa.

Co fraza:

„Każdy obiekt, który obsługuje w operatora mogą być przekazywane jako wartość wyborów, tak DICT przedmiotów, obiektów, niestandardowe zestawy pojemników itp są obsługiwane.”

dotyczy to wybory argument, że mogą być przekazywane z add_argument funkcji - nie do typu argument.

Najprościej jest prawdopodobnie zaakceptować argumentu jako ciąg znaków, a następnie przekształcić go za pomocą json możliwości Pythona:

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

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

Następnie można przejść do słownika w postaci łańcucha. Można spróbować json koder/dekoder dla siebie w konsoli Pythona, aby zobaczyć jak to działa:

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

EDIT: hpaulj wskazał mi się, że można „włamać” się parametr typu przez przekazanie go 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 

Powód, dla którego to działa, jest całkiem interesujący, ponieważ wewnętrznie argparse użyje tylko wartości parametru jako funkcji do przekonwertowania argumentu. tj. jeśli type = int, użyje ono int (arg) lub if type = json.loads, a następnie json.ładunki (arg)

To oznacza również, że można przekazać dowolną funkcję, która pobiera jeden parametr jako argument do pisania i wykonywania niestandardowych konwersji, jeśli chcesz :)

+20

'type = json.loads' works – hpaulj

+1

To ma sens, ponieważ, jak wspomniałem powyżej, parametr przekazywany do typu jest obsługiwany przez umieszczenie argumentu w nawiasie. Dziękuję za wskazanie tego. –

+0

Nie nazwałbym tego "hack". Tak naprawdę ma działać argument typu – mdw7326

Powiązane problemy