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"}
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'})
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.)
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.
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())
juste un autre moyen facile:
parser = argparse.ArgumentParser()
parser.add_argument('--key1')
parser.add_argument('--key2')
args = parser.parse_args()
my_dict = args.__dict__
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.