webentwicklung-frage-antwort-db.com.de

Irgendeine Möglichkeit, ordentlich Wörterbücher hübsch zu drucken?

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.

84
Elias Zamaria

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
116
webwurst

Das Folgende funktioniert, wenn die Reihenfolge Ihrer OrderedDict eine Alpha-Sortierung ist, da pprint ein Diktier vor dem Drucken sortiert.

pprint(dict(o.items()))
14
kzh

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)])]

8
martineau

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)
]))
7
Ilya Prokin

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'}
5
rumpel
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)
2
Jakob Bowyer

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!

2
flutefreak7

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.

1
Bill M.

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
0
LondonRob

Sie können diese Vereinfachung der Antwort " kzh " auch verwenden:

pprint(data.items(), indent=4)

Es bewahrt die Reihenfolge und gibt fast dasselbe aus wie die webwurst answer (print durch json dump).

0
Albert Alomar

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
# }
0
martineau

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.

0
Karl Rosaen

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"
}
0
CHINTAN VADGAMA