web-dev-qa-db-fra.com

Python argparse dict arg

Je souhaite recevoir un argument dict(str -> str) à partir de la ligne de commande. Est-ce que argparse.ArgumentParser le fournit? Ou une autre bibliothèque?

Pour la ligne de commande:

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

J'attends le dictionnaire suivant:

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

Voici une autre solution utilisant une action custom, si vous souhaitez spécifier des paires de clés dict ensemble, séparées par des virgules -

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

Fonctionnement:

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

Sortie:

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

Si vous voulez utiliser nargs au lieu de séparer par une virgule:

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

Fonctionnement

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

Les sorties:

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

Je voudrais utiliser quelque chose comme ça:

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)

Vous pouvez créer une action personnalisée qui "ajouterait" une paire clé-valeur analysée directement dans un dictionnaire, plutôt que de simplement accumuler une liste de (key, value) tuples. (Ce que je vois, c’est ce que skyline75489 a fait; ma réponse diffère en utilisant une seule option --keyvalue avec un type personnalisé au lieu d’options séparées --key et --value pour spécifier des paires.)

16
chepner

Python reçoit des arguments sous la forme d'un tableau argv. Vous pouvez l'utiliser pour créer le dictionnaire dans le programme même.

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

Pour la ligne de commande:

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

Sortie:

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

Remarque: les arguments seront dans une chaîne, vous devrez donc les convertir pour stocker des valeurs numériques.

J'espère que ça aide.

3
divyum

Arguments du dictionnaire argparse à une ligne 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())
1
miszel

juste un autre moyen facile:

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

Une manière simple d’analyser une entrée telle que:

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

est: 

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

qui devrait produire (si mon analyseur mental est correct)

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

Vous devriez pouvoir construire un dictionnaire à partir de cela avec:

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

L'utilisation de args.dict pour l'attribuer à une variable portant ce nom nécessite quelques astuces non python. Le mieux serait de créer un élément dans un autre dictionnaire portant ce nom.

another_dict = {args.dict: adict}

Cette solution n'effectue pas beaucoup de vérification d'erreur. Par exemple, cela ne garantit pas qu'il existe le même nombre de clés et de valeurs. Cela ne vous laisserait pas non plus créer plusieurs dictionnaires (c'est-à-dire des arguments répétés --dict). Il ne nécessite aucune commande spéciale. --dict peut se produire après une paire --key key1. Plusieurs arguments --value peuvent être ensemble. 

Lier le key=value ensemble comme chepner résout un certain nombre de ces problèmes.

0
hpaulj