web-dev-qa-db-fra.com

Accepter un dictionnaire comme argument avec argparse et python

J'essaie d'accepter un argument de type = dict avec argparse mais peu importe l'entrée, il donne une erreur de valeur de dict invalide.

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

C'est ce qui se passe lorsque j'essaie de passer un dictionnaire au script

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

En regardant les documents, je pense que ce serait possible.

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

"Tout objet qui prend en charge l'opérateur in peut être transmis comme valeur de choix, donc les objets dict, set objets, conteneurs personnalisés, etc. sont tous pris en charge."

41
user2745896

Je ne pense pas qu'il soit possible de passer un dictionnaire comme argument dans la ligne de commande car il n'existe pas de fonction de conversion de chaîne en dict ( [~ # ~] edit [~ # ~] : Un hack est possible, voir ci-dessous). Ce que vous dites essentiellement python à faire est:

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

Ce qui si vous l'essayez dans la console python, ne fonctionne pas.

Quelle est la phrase:

"Tout objet qui prend en charge l'opérateur in peut être transmis comme valeur de choix, donc les objets dict, set objets, conteneurs personnalisés, etc. sont tous pris en charge."

se réfère à l'argument de choix qui peut être passé avec la fonction add_argument - pas à l'argument de type .

Votre meilleur pari est probablement d'accepter votre argument sous forme de chaîne, puis de le convertir en utilisant les capacités json de python:

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

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

Vous pouvez ensuite passer un dictionnaire sous la forme d'une chaîne. Vous pouvez essayer l'encodeur/décodeur json par vous-même dans la console python pour voir comment cela fonctionne:

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

[~ # ~] modifier [~ # ~] : hpaulj m'a fait remarquer que vous pouvez "pirater" le type paramètre en le passant 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

La raison pour laquelle cela fonctionne est en fait assez intéressante car en interne argparse utilisera simplement la valeur du paramètre comme fonction pour convertir l'argument. c'est-à-dire que si type = int alors il utilisera int (arg) ou si type = json.loads alors json.loads (arg)

Cela signifie également que vous pouvez passer n'importe quelle fonction qui prend un seul paramètre comme argument pour taper et effectuer des conversions personnalisées si vous en avez besoin :)

57
Michael Aquilina