Un moyen d'imprimer correctement les dictionnaires commandés?
j'aime le module pprint en Python. Je l'utilise beaucoup pour tester et déboguer. J'utilise souvent l'option width pour m'assurer que la sortie s'adapte bien dans ma fenêtre de terminal.
il a bien fonctionné jusqu'à ce qu'ils ont ajouté le nouveau type de dictionnaire ordonné en python 2.7 (une autre caractéristique cool que j'aime vraiment). Si j'essaie d'imprimer un dictionnaire commandé, ça ne se voit pas bien. Au lieu d'avoir chaque paire clé-valeur, sur sa propre ligne, tout s'affiche sur une longue ligne, qui s'enroule plusieurs fois et est difficile à lire.
est-ce que quelqu'un ici a un moyen de le faire imprimer correctement, comme les vieux dictionnaires non ordonnés? Je pourrais probablement trouver quelque chose, peut-être en utilisant le PrettyPrinter.méthode de format, si je passe assez de temps, mais je me demande si quelqu'un ici sait déjà d'une solution.
mise à jour: j'ai déposé un rapport de bogue pour cela. Vous pouvez le voir à http://bugs.python.org/issue10592 .
12 réponses
comme solution temporaire, vous pouvez essayer le dumping au format JSON. Vous perdez quelques informations de type, mais il semble agréable et garde l'ordre.
import json
pprint(data, indent=4)
# ^ugly
print(json.dumps(data, indent=4))
# ^nice
ce qui suit fonctionnera si l'ordre de votre OrderedDict est un tri alpha, puisque pprint triera un dict avant impression.
pprint(dict(o.items()))
Voici une autre réponse qui fonctionne en outrepassant et en utilisant la fonction stock pprint()
en interne. Contrairement à mon plus tôt un il will poignée OrderedDict
l 'intérieur d'un autre conteneur comme un list
et devrait également être en mesure de gérer tous les mots clés facultatifs arguments donnés - cependant, il n'a pas le même degré de contrôle sur la sortie que l'autre permis.
rediriger la sortie de la fonction stock dans un tampon temporaire et ensuite le mot l'enveloppe avant de l'envoyer sur le flux de sortie. Alors que la sortie finale produite n'est pas exceptionnellement jolie, elle est décente et peut être "assez bonne" à utiliser comme solution de contournement.
mise à Jour 2.0
simplifié en utilisant la bibliothèque standard textwrap
module, et modifié pour fonctionner dans
les deux Python 2 et 3.
from collections import OrderedDict
try:
from cStringIO import StringIO
except ImportError: # Python 3
from io import StringIO
from pprint import pprint as pp_pprint
import sys
import textwrap
def pprint(object, **kwrds):
try:
width = kwrds['width']
except KeyError: # unlimited, use stock function
pp_pprint(object, **kwrds)
return
buffer = StringIO()
stream = kwrds.get('stream', sys.stdout)
kwrds.update({'stream': buffer})
pp_pprint(object, **kwrds)
words = buffer.getvalue().split()
buffer.close()
# word wrap output onto multiple lines <= width characters
try:
print >> stream, textwrap.fill(' '.join(words), width=width)
except TypeError: # Python 3
print(textwrap.fill(' '.join(words), width=width), file=stream)
d = dict((('john',1), ('paul',2), ('mary',3)))
od = OrderedDict((('john',1), ('paul',2), ('mary',3)))
lod = [OrderedDict((('john',1), ('paul',2), ('mary',3))),
OrderedDict((('moe',1), ('curly',2), ('larry',3))),
OrderedDict((('weapons',1), ('mass',2), ('destruction',3)))]
Sortie de l'échantillon:
pprint(d, width=40)
{'john': 1, 'mary': 3, 'paul': 2}
pprint(od, width=40)
" OrderedDict([('john', 1), ('paul', 2),
('mary', 3)])
pprint(lod, width=40)
" [OrderedDict([('john', 1), ('paul', 2),
('mary', 3)]), OrderedDict([('moe', 1),
('curly', 2), ('larry', 3)]),
OrderedDict([('weapons', 1), ('mass',
2), ('destruction', 3)])]
pour imprimer un dict commandé, p.ex.
from collections import OrderedDict
d=OrderedDict([
('a', OrderedDict([
('a1',1),
('a2','sss')
])),
('b', OrderedDict([
('b1', OrderedDict([
('bb1',1),
('bb2',4.5)])),
('b2',4.5)
])),
])
je ne
def dict_or_OrdDict_to_formatted_str(OD, mode='dict', s="", indent=' '*4, level=0):
def is_number(s):
try:
float(s)
return True
except ValueError:
return False
def fstr(s):
return s if is_number(s) else '"%s"'%s
if mode != 'dict':
kv_tpl = '("%s", %s)'
ST = 'OrderedDict([\n'; END = '])'
else:
kv_tpl = '"%s": %s'
ST = '{\n'; END = '}'
for i,k in enumerate(OD.keys()):
if type(OD[k]) in [dict, OrderedDict]:
level += 1
s += (level-1)*indent+kv_tpl%(k,ST+dict_or_OrdDict_to_formatted_str(OD[k], mode=mode, indent=indent, level=level)+(level-1)*indent+END)
level -= 1
else:
s += level*indent+kv_tpl%(k,fstr(OD[k]))
if i!=len(OD)-1:
s += ","
s += "\n"
return s
print dict_or_OrdDict_to_formatted_str(d)
qui donne
"a": {
"a1": 1,
"a2": "sss"
},
"b": {
"b1": {
"bb1": 1,
"bb2": 4.5
},
"b2": 4.5
}
ou
print dict_or_OrdDict_to_formatted_str(d, mode='OD')
qui donne
("a", OrderedDict([
("a1", 1),
("a2", "sss")
])),
("b", OrderedDict([
("b1", OrderedDict([
("bb1", 1),
("bb2", 4.5)
])),
("b2", 4.5)
]))
Voici une façon de pirater l'implémentation de pprint
.
pprint
trie les clés avant l'impression, donc pour préserver l'ordre, nous devons juste faire le tri des clés comme nous le voulons.
notez que cela a un impact sur la fonction items()
.
Ainsi, vous pourriez vouloir préserver et restaurer les fonctions overridden après avoir fait l'empreinte.
from collections import OrderedDict
import pprint
class ItemKey(object):
def __init__(self, name, position):
self.name = name
self.position = position
def __cmp__(self, b):
assert isinstance(b, ItemKey)
return cmp(self.position, b.position)
def __repr__(self):
return repr(self.name)
OrderedDict.items = lambda self: [
(ItemKey(name, i), value)
for i, (name, value) in enumerate(self.iteritems())]
OrderedDict.__repr__ = dict.__repr__
a = OrderedDict()
a[4] = '4'
a[1] = '1'
a[2] = '2'
print pprint.pformat(a) # {4: '4', 1: '1', 2: '2'}
C'est assez brut, mais j'avais juste besoin d'un moyen de visualiser une structure de données composée de toutes les applications arbitraires et Iterables et c'est ce que j'ai trouvé avant d'abandonner. Il est récursif,donc il tombera à travers des structures imbriquées et des listes très bien. J'ai utilisé la cartographie et les classes de base abstraites itérables des collections pour gérer à peu près n'importe quoi.
je visais une sortie proche de celle de yaml avec du code Python concis, mais je n'ai pas tout à fait réussi.
def format_structure(d, level=0):
x = ""
if isinstance(d, Mapping):
lenk = max(map(lambda x: len(str(x)), d.keys()))
for k, v in d.items():
key_text = "\n" + " "*level + " "*(lenk - len(str(k))) + str(k)
x += key_text + ": " + format_structure(v, level=level+lenk)
elif isinstance(d, Iterable) and not isinstance(d, basestring):
for e in d:
x += "\n" + " "*level + "- " + format_structure(e, level=level+4)
else:
x = str(d)
return x
et certaines données d'essai en utilisant OrderedDict et des listes de OrderedDicts... (sheesh Python a vraiment besoin d'une ordonnance littéraire...)
d = OrderedDict([("main",
OrderedDict([("window",
OrderedDict([("size", [500, 500]),
("position", [100, 900])])),
("splash_enabled", True),
("theme", "Dark")])),
("updates",
OrderedDict([("automatic", True),
("servers",
[OrderedDict([("url", "http://server1.com"),
("name", "Stable")]),
OrderedDict([("url", "http://server2.com"),
("name", "Beta")]),
OrderedDict([("url", "http://server3.com"),
("name", "Dev")])]),
("prompt_restart", True)])),
("logging",
OrderedDict([("enabled", True),
("rotate", True)]))])
print format_structure(d)
donne la production suivante:
main:
window:
size:
- 500
- 500
position:
- 100
- 900
splash_enabled: True
theme: Dark
updates:
automatic: True
servers:
-
url: http://server1.com
name: Stable
-
url: http://server2.com
name: Beta
-
url: http://server3.com
name: Dev
prompt_restart: True
logging:
enabled: True
rotate: True
j'ai eu quelques pensées le long de la façon d'utiliser str.format () pour un meilleur alignement, mais je n'avais pas envie d'y creuser. Vous aurez besoin de spécifier dynamiquement les largeurs de champ en fonction du type d'alignement que vous voulez, serait soit délicat ou encombrant.
quoi qu'il en soit, cela me montre mes données de manière hiérarchique lisible, de sorte que cela fonctionne pour moi!
def pprint_od(od):
print "{"
for key in od:
print "%s:%s,\n" % (key, od[key]) # Fixed syntax
print "}"
vous Y allez ^^
for item in li:
pprint_od(item)
ou
(pprint_od(item) for item in li)
la méthode pprint()
ne fait qu'invoquer la méthode __repr__()
des choses qu'elle contient, et OrderedDict
ne semble pas faire grand chose dans sa méthode (ou n'en a pas une ou quelque chose).
Voici une solution bon marché qui devrait fonctionner si vous ne vous souciez pas que la commande soit VISIBLE dans la sortie de PPRINT , qui peut être un grand si:
class PrintableOrderedDict(OrderedDict):
def __repr__(self):
return dict.__repr__(self)
en fait, je suis surpris que l'ordre ne soit pas préservé... ah bien.
vous pourriez redéfinir pprint()
et intercepter les appels pour OrderedDict
's. Voici une illustration simple. Comme écrit, le OrderedDict
outrepasse le code stream
, indent
, width
, ou depth
mots-clés qui peuvent avoir été passés, mais pourraient être améliorés pour les mettre en œuvre. Malheureusement, cette technique ne les manipule pas à l'intérieur d'un autre conteneur, comme un list
de OrderDict
's
from collections import OrderedDict
from pprint import pprint as pp_pprint
def pprint(obj, *args, **kwrds):
if not isinstance(obj, OrderedDict):
# use stock function
return pp_pprint(obj, *args, **kwrds)
else:
# very simple sample custom implementation...
print "{"
for key in obj:
print " %r:%r" % (key, obj[key])
print "}"
l = [10, 2, 4]
d = dict((('john',1), ('paul',2), ('mary',3)))
od = OrderedDict((('john',1), ('paul',2), ('mary',3)))
pprint(l, width=4)
# [10,
# 2,
# 4]
pprint(d)
# {'john': 1, 'mary': 3, 'paul': 2}
pprint(od)
# {
# 'john':1
# 'paul':2
# 'mary':3
# }
si les articles du dictionnaire sont tous d'un type, vous pouvez utiliser l'étonnante bibliothèque de traitement de données pandas
:
>>> import pandas as pd
>>> x = {'foo':1, 'bar':2}
>>> pd.Series(x)
bar 2
foo 1
dtype: int64
ou
>>> import pandas as pd
>>> x = {'foo':'bar', 'baz':'bam'}
>>> pd.Series(x)
baz bam
foo bar
dtype: object
vous pouvez également utiliser cette simplification de la kzh réponse:
pprint(data.items(), indent=4)
il préserve l'ordre et produira presque le même que le webwurst réponse ( impression par JSON dump ).
Voici ma démarche assez de pression pour un OrderedDict
from collections import OrderedDict
import json
d = OrderedDict()
d['duck'] = 'alive'
d['parrot'] = 'dead'
d['penguin'] = 'exploded'
d['Falcon'] = 'discharged'
print d
print json.dumps(d,indent=4)
OutPut:
OrderedDict([('duck', 'alive'), ('parrot', 'dead'), ('penguin', 'exploded'), ('Falcon', 'discharged')])
{
"duck": "alive",
"parrot": "dead",
"penguin": "exploded",
"Falcon": "discharged"
}
si vous voulez pretty print dictionary avec des clés dans l'ordre trié
print json.dumps(indent=4,sort_keys=True)
{
"Falcon": "discharged",
"duck": "alive",
"parrot": "dead",
"penguin": "exploded"
}