Ich mag das pprint-Modul in Python. Ich verwende es häufig zum Testen und Debuggen. Ich verwende häufig die Option width, um sicherzustellen, dass die Ausgabe gut in mein Terminalfenster passt.
Es hat gut funktioniert, bis sie den neuen geordneten Wörterbuchtyp in Python 2.7 hinzugefügt haben (ein weiteres cooles Feature, das ich wirklich mag). Wenn ich versuche, ein geordnetes Wörterbuch hübsch zu drucken, wird es nicht schön angezeigt. Anstatt jedes Schlüssel-Wert-Paar in einer eigenen Zeile zu haben, wird das Ganze in einer langen Zeile angezeigt, die viele Male umläuft und schwer zu lesen ist.
Hat jemand hier eine Möglichkeit, es gut drucken zu lassen, wie die alten ungeordneten Wörterbücher? Ich könnte wahrscheinlich etwas herausfinden, möglicherweise mit der PrettyPrinter.format-Methode, wenn ich genug Zeit verbringe, aber ich frage mich, ob hier schon jemand eine Lösung kennt.
UPDATE: Ich habe dafür einen Fehlerbericht eingereicht. Sie können es unter http://bugs.python.org/issue10592 sehen.
Als vorübergehende Problemumgehung können Sie versuchen, ein Dumping im JSON-Format durchzuführen. Sie verlieren zwar einige Typinformationen, sehen aber nett aus und behalten die Reihenfolge.
import json
pprint(data, indent=4)
# ^ugly
print(json.dumps(data, indent=4))
# ^Nice
Das Folgende funktioniert, wenn die Reihenfolge Ihrer OrderedDict eine Alpha-Sortierung ist, da pprint ein Diktier vor dem Drucken sortiert.
pprint(dict(o.items()))
Hier ist eine weitere Antwort, die durch Überschreiben und interne Verwendung der Funktion stock pprint()
funktioniert. Anders als mein früheres behandelt es OrderedDict
in einem anderen Container wie einem list
und sollte auch jedes verarbeiten können optionale Schlüsselwortargumente angegeben - jedoch hat es nicht die gleiche Kontrolle über die Ausgabe wie das andere.
Es wird ausgeführt, indem die Ausgabe der Aktienfunktion in einen temporären Puffer umgeleitet wird, der dann von Word umgebrochen wird, bevor er an den Ausgabestream gesendet wird. Obwohl die endgültige Ausgabe nicht besonders hübsch ist, ist sie anständig und kann "gut genug" sein, um sie zu umgehen.
Update 2.0
Vereinfacht durch Verwendung des Moduls textwrap
der Standardbibliothek und geändert, um in beiden Python 2 & 3 zu funktionieren.
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)))]
Beispielausgabe:
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)])]
Um ein bestelltes Diktat zu drucken, z.
from collections import OrderedDict
d=OrderedDict([
('a', OrderedDict([
('a1',1),
('a2','sss')
])),
('b', OrderedDict([
('b1', OrderedDict([
('bb1',1),
('bb2',4.5)])),
('b2',4.5)
])),
])
Ich mache
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)
Was bringt
"a": {
"a1": 1,
"a2": "sss"
},
"b": {
"b1": {
"bb1": 1,
"bb2": 4.5
},
"b2": 4.5
}
oder
print dict_or_OrdDict_to_formatted_str(d, mode='OD')
was ergibt
("a", OrderedDict([
("a1", 1),
("a2", "sss")
])),
("b", OrderedDict([
("b1", OrderedDict([
("bb1", 1),
("bb2", 4.5)
])),
("b2", 4.5)
]))
Dies ist eine Methode, die die Implementierung von pprint
.pprint
hackt, die Schlüssel vor dem Drucken sortiert. Um die Reihenfolge zu erhalten, müssen wir die Schlüssel nur so sortieren, wie wir es möchten.
Beachten Sie, dass sich dies auf die Funktion items()
auswirkt. Sie sollten die überschriebenen Funktionen daher beibehalten und wiederherstellen, nachdem Sie den pprint ausgeführt haben.
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'}
def pprint_od(od):
print "{"
for key in od:
print "%s:%s,\n" % (key, od[key]) # Fixed syntax
print "}"
Da gehst du hin ^^
for item in li:
pprint_od(item)
oder
(pprint_od(item) for item in li)
Dies ist ziemlich grob, aber ich brauchte nur einen Weg, um eine Datenstruktur zu visualisieren, die aus beliebigen Mappings und Iterables besteht. Dies ist, was ich vor dem Aufgeben gefunden habe. Es ist rekursiv, sodass es durch verschachtelte Strukturen und Listen hindurchgeht. Ich habe die abstrakten Basisklassen Mapping und Iterable aus Sammlungen verwendet, um so ziemlich alles zu handhaben.
Ich zielte auf fast yaml-artige Ausgabe mit prägnantem Python-Code, habe es aber nicht ganz geschafft.
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
und einige Testdaten mit OrderedDict und Listen von OrderedDicts ... (sheesh Python benötigt OrderedDict-Literale sooo sehr ...)
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)
ergibt folgende Ausgabe:
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
Ich hatte einige Gedanken über die Verwendung von str.format (), um die Ausrichtung zu verbessern, hatte aber keine Lust dazu. Sie müssen die Feldbreiten abhängig von der gewünschten Ausrichtung dynamisch angeben, was entweder schwierig oder umständlich werden würde.
Auf jeden Fall zeigt mir dies meine Daten in lesbarer hierarchischer Weise, so dass es für mich funktioniert!
Die pprint()
-Methode ruft lediglich die __repr__()
-Methode der Dinge auf, und OrderedDict
scheint in ihrer Methode nicht viel zu tun (oder hat keine oder etwas).
Hier ist eine billige Lösung, die funktionieren sollte WENN SIE SICH NICHT BEOBACHTET WERDEN, DASS DIE BESTELLUNG IM PPRINT-AUSGABE SICHTBAR IST , was ein großes sein kann, wenn
class PrintableOrderedDict(OrderedDict):
def __repr__(self):
return dict.__repr__(self)
Ich bin eigentlich überrascht, dass die Reihenfolge nicht erhalten bleibt ... na ja.
Wenn die Wörterbuchelemente alle von einem Typ sind, können Sie die erstaunliche Datenverarbeitungsbibliothek pandas
verwenden:
>>> import pandas as pd
>>> x = {'foo':1, 'bar':2}
>>> pd.Series(x)
bar 2
foo 1
dtype: int64
oder
>>> import pandas as pd
>>> x = {'foo':'bar', 'baz':'bam'}
>>> pd.Series(x)
baz bam
foo bar
dtype: object
Sie könnten pprint()
neu definieren und Aufrufe für OrderedDict
abfangen. Hier ist eine einfache Illustration. Wie geschrieben, ignoriert der OrderedDict
-Überschreibungscode alle optionalen stream
-, indent
-, width
- oder depth
-Schlüsselwörter, die möglicherweise übergeben wurden, aber zur Implementierung erweitert werden könnten. Leider behandelt diese Technik sie nicht in einem anderen Container, z. B. einer list
von OrderDict
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
# }
Ich habe diesen unheiligen Affen-Patch-basierten Hack auf python3.5 getestet und es funktioniert:
pprint.PrettyPrinter._dispatch[pprint._collections.OrderedDict.__repr__] = pprint.PrettyPrinter._pprint_dict
def unsorted_pprint(data):
def fake_sort(*args, **kwargs):
return args[0]
orig_sorted = __builtins__.sorted
try:
__builtins__.sorted = fake_sort
pprint.pprint(data)
finally:
__builtins__.sorted = orig_sorted
Sie legen fest, dass pprint
die übliche diktbasierte Zusammenfassung verwendet, und deaktivieren außerdem die Sortierung für die Dauer des Anrufs, damit tatsächlich keine Schlüssel zum Drucken sortiert werden.
Hier ist mein Ansatz, um ein OrderedDict zu drucken
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"
}
Wenn Sie das Wörterbuch mit den Schlüsseln in sortierter Reihenfolge ausdrucken möchten
print json.dumps(indent=4,sort_keys=True)
{
"Falcon": "discharged",
"duck": "alive",
"parrot": "dead",
"penguin": "exploded"
}