it-swarm.com.de

Wie kann man verschachtelte Wörterbücher schön drucken?

Wie kann ich ein Wörterbuch mit einer Tiefe von ~ 4 in Python drucken? Ich habe versucht, mit pprint() ziemlich zu drucken, aber es hat nicht funktioniert:

import pprint 
pp = pprint.PrettyPrinter(indent=4)
pp.pprint(mydict)

Ich möchte einfach eine Einrückung ("\t") für jede Verschachtelung, damit ich so etwas bekomme:

key1
    value1
    value2
    key2
       value1
       value2

usw. 

Wie kann ich das machen?

198
user248237dfsf

Ich bin nicht sicher, wie genau die Formatierung aussehen soll, aber Sie könnten mit einer Funktion wie dieser beginnen:

def pretty(d, indent=0):
   for key, value in d.items():
      print('\t' * indent + str(key))
      if isinstance(value, dict):
         pretty(value, indent+1)
      else:
         print('\t' * (indent+1) + str(value))

( für Python-2-Benutzer: Importieren Sie die Druckfunktion aus __future__ )

107
sth

Mein erster Gedanke war, dass der JSON-Serializer wahrscheinlich sehr gut in verschachtelten Wörterbüchern funktioniert. Ich würde also schummeln und das verwenden:

>>> import json
>>> print json.dumps({'a':2, 'b':{'x':3, 'y':{'t1': 4, 't2':5}}},
...                  sort_keys=True, indent=4)
{
    "a": 2,
    "b": {
        "x": 3,
        "y": {
            "t1": 4,
            "t2": 5
        }
    }
}
397
Ken

Sie könnten versuchen, YAML über PyYAML . Sein Ausgang kann fein eingestellt werden. Ich würde vorschlagen, mit dem Folgenden zu beginnen:

print yaml.dump(data, allow_unicode=True, default_flow_style=False)

Das Ergebnis ist sehr lesbar; es kann bei Bedarf auch zurück zu Python analysiert werden.

Bearbeiten:

Beispiel:

>>> import yaml
>>> data = {'a':2, 'b':{'x':3, 'y':{'t1': 4, 't2':5}}}
>>> print yaml.dump(data, default_flow_style=False)
a: 2
b:
  x: 3
  y:
    t1: 4
    t2: 5
43

Nach allem, was getan wurde, sehe ich keinen hübschen Drucker, der zumindest die Ausgabe des Python-Interpreters mit sehr einfacher Formatierung nachahmt.

class Formatter(object):
    def __init__(self):
        self.types = {}
        self.htchar = '\t'
        self.lfchar = '\n'
        self.indent = 0
        self.set_formater(object, self.__class__.format_object)
        self.set_formater(dict, self.__class__.format_dict)
        self.set_formater(list, self.__class__.format_list)
        self.set_formater(Tuple, self.__class__.format_Tuple)

    def set_formater(self, obj, callback):
        self.types[obj] = callback

    def __call__(self, value, **args):
        for key in args:
            setattr(self, key, args[key])
        formater = self.types[type(value) if type(value) in self.types else object]
        return formater(self, value, self.indent)

    def format_object(self, value, indent):
        return repr(value)

    def format_dict(self, value, indent):
        items = [
            self.lfchar + self.htchar * (indent + 1) + repr(key) + ': ' +
            (self.types[type(value[key]) if type(value[key]) in self.types else object])(self, value[key], indent + 1)
            for key in value
        ]
        return '{%s}' % (','.join(items) + self.lfchar + self.htchar * indent)

    def format_list(self, value, indent):
        items = [
            self.lfchar + self.htchar * (indent + 1) + (self.types[type(item) if type(item) in self.types else object])(self, item, indent + 1)
            for item in value
        ]
        return '[%s]' % (','.join(items) + self.lfchar + self.htchar * indent)

    def format_Tuple(self, value, indent):
        items = [
            self.lfchar + self.htchar * (indent + 1) + (self.types[type(item) if type(item) in self.types else object])(self, item, indent + 1)
            for item in value
        ]
        return '(%s)' % (','.join(items) + self.lfchar + self.htchar * indent)

Um es zu initialisieren:

pretty = Formatter()

Es kann das Hinzufügen von Formatierern für definierte Typen unterstützen. Sie müssen lediglich eine Funktion wie diese erstellen und sie mit set_formater an den gewünschten Typ binden.

from collections import OrderedDict

def format_ordereddict(self, value, indent):
    items = [
        self.lfchar + self.htchar * (indent + 1) +
        "(" + repr(key) + ', ' + (self.types[
            type(value[key]) if type(value[key]) in self.types else object
        ])(self, value[key], indent + 1) + ")"
        for key in value
    ]
    return 'OrderedDict([%s])' % (','.join(items) +
           self.lfchar + self.htchar * indent)
pretty.set_formater(OrderedDict, format_ordereddict)

Aus historischen Gründen belasse ich den vorherigen hübschen Drucker, der eine Funktion anstelle einer Klasse war, aber beide können auf dieselbe Weise verwendet werden. Die Klassenversion lässt einfach mehr zu:

def pretty(value, htchar='\t', lfchar='\n', indent=0):
    nlch = lfchar + htchar * (indent + 1)
    if type(value) is dict:
        items = [
            nlch + repr(key) + ': ' + pretty(value[key], htchar, lfchar, indent + 1)
            for key in value
        ]
        return '{%s}' % (','.join(items) + lfchar + htchar * indent)
    Elif type(value) is list:
        items = [
            nlch + pretty(item, htchar, lfchar, indent + 1)
            for item in value
        ]
        return '[%s]' % (','.join(items) + lfchar + htchar * indent)
    Elif type(value) is Tuple:
        items = [
            nlch + pretty(item, htchar, lfchar, indent + 1)
            for item in value
        ]
        return '(%s)' % (','.join(items) + lfchar + htchar * indent)
    else:
        return repr(value)

Um es zu benutzen :

>>> a = {'list':['a','b',1,2],'dict':{'a':1,2:'b'},'Tuple':('a','b',1,2),'function':pretty,'unicode':u'\xa7',("Tuple","key"):"valid"}
>>> a
{'function': <function pretty at 0x7fdf555809b0>, 'Tuple': ('a', 'b', 1, 2), 'list': ['a', 'b', 1, 2], 'dict': {'a': 1, 2: 'b'}, 'unicode': u'\xa7', ('Tuple', 'key'): 'valid'}
>>> print(pretty(a))
{
    'function': <function pretty at 0x7fdf555809b0>,
    'Tuple': (
        'a',
        'b',
        1,
        2
    ),
    'list': [
        'a',
        'b',
        1,
        2
    ],
    'dict': {
        'a': 1,
        2: 'b'
    },
    'unicode': u'\xa7',
    ('Tuple', 'key'): 'valid'
}

Im Vergleich zu anderen Versionen:

  • Diese Lösung sucht direkt nach Objekttyp, sodass Sie fast alles drucken können, nicht nur Listen oder Diktate.
  • Hat keine Abhängigkeit.
  • Alles wird in einen String eingefügt, damit Sie machen können, was Sie wollen.
  • Die Klasse und die Funktion wurde getestet und funktioniert mit Python 2.7 und 3.4.
  • Sie können alle Arten von Objekten enthalten. Dies ist ihre Repräsentation und nicht ihr Inhalt, der in das Ergebnis eingefügt wird.
  • Mit der Klassenversion können Sie die Formatierung für jeden gewünschten Objekttyp hinzufügen oder für bereits definierte ändern.
  • der Schlüssel kann einen beliebigen gültigen Typ haben.
  • Einzugs- und Zeilenumbruch-Zeichen können für alles geändert werden, was wir möchten.
  • Dikt, Liste und Tupel sind hübsch gedruckt.
30
y.petremann

Eine weitere Option mit yapf

from pprint import pformat
from yapf.yapflib.yapf_api import FormatCode

dict_example = {'1': '1', '2': '2', '3': [1, 2, 3, 4, 5], '4': {'1': '1', '2': '2', '3': [1, 2, 3, 4, 5]}}
dict_string = pformat(dict_example)
formatted_code, _ = FormatCode(dict_string)

print(formatted_code)

Ausgabe:

{
    '1': '1',
    '2': '2',
    '3': [1, 2, 3, 4, 5],
    '4': {
        '1': '1',
        '2': '2',
        '3': [1, 2, 3, 4, 5]
    }
}
6
Eyal Levin

Ich nahm sths answer und modifizierte es leicht, um meinen Bedürfnissen von verschachtelten Wörterbüchern und Listen zu entsprechen:

def pretty(d, indent=0):
    if isinstance(d, dict):
        for key, value in d.iteritems():
            print '\t' * indent + str(key)
            if isinstance(value, dict) or isinstance(value, list):
                pretty(value, indent+1)
            else:
                print '\t' * (indent+1) + str(value)
    Elif isinstance(d, list):
        for item in d:
            if isinstance(item, dict) or isinstance(item, list):
                pretty(item, indent+1)
            else:
                print '\t' * (indent+1) + str(item)
    else:
        pass

Was gibt mir dann Ausgabe wie:

>>> 
xs:schema
    @xmlns:xs
        http://www.w3.org/2001/XMLSchema
    xs:redefine
        @schemaLocation
            base.xsd
        xs:complexType
            @name
                Extension
            xs:complexContent
                xs:restriction
                    @base
                        Extension
                    xs:sequence
                        xs:element
                            @name
                                Policy
                            @minOccurs
                                1
                            xs:complexType
                                xs:sequence
                                    xs:element
                                            ...
3
Jamie Ivanov

Wie andere geschrieben haben, können Sie Rekursion/DFS verwenden, um die verschachtelten Wörterbuchdaten zu drucken und rekursiv aufzurufen, wenn es sich um ein Wörterbuch handelt. Andernfalls drucken Sie die Daten.

def print_json(data):
    if type(data) == dict:
            for k, v in data.items():
                    print k
                    print_json(v)
    else:
            print data
3

Schmollmund kann alles, was Sie darauf werfen, ziemlich gut ausdrucken (zB data von einer anderen Antwort ausleihen):

data = {'a':2, 'b':{'x':3, 'y':{'t1': 4, 't2':5}}}
pout.vs(data)

würde zu einer auf dem Bildschirm gedruckten Ausgabe führen:

{
    'a': 2,
    'b':
    {
        'y':
        {
            't2': 5,
            't1': 4
        },
        'x': 3
    }
}

oder Sie können die formatierte Zeichenfolgenausgabe Ihres Objekts zurückgeben:

v = pout.s(data)

Sein hauptsächlicher Anwendungsfall ist für das Debuggen, so dass es nicht an Objektinstanzen oder anderen Objekten drosselt und die Unicode-Ausgabe wie erwartet verarbeitet. Sie arbeitet in Python 2.7 und 3.

Disclosure: Ich bin Autor und Betreuer von Schmollmund.

1
Jaymon
This class prints out a complex nested dictionary with sub dictionaries and sub lists.  
##
## Recursive class to parse and print complex nested dictionary
##

class NestedDictionary(object):
    def __init__(self,value):
        self.value=value

    def print(self,depth):
        spacer="--------------------"
        if type(self.value)==type(dict()):
            for kk, vv in self.value.items():
                if (type(vv)==type(dict())):
                    print(spacer[:depth],kk)
                    vvv=(NestedDictionary(vv))
                    depth=depth+3
                    vvv.print(depth)
                    depth=depth-3
                else:
                    if (type(vv)==type(list())):
                        for i in vv:
                            vvv=(NestedDictionary(i))
                            depth=depth+3
                            vvv.print(depth)
                            depth=depth-3
                    else:
                        print(spacer[:depth],kk,vv) 

##
## Instatiate and execute - this prints complex nested dictionaries
## with sub dictionaries and sub lists
## 'something' is a complex nested dictionary

MyNest=NestedDictionary(weather_com_result)
MyNest.print(0)
1
Bob Lockwood

Sth, ich senke das ist schön;)

def pretty(d, indent=0):
    for key, value in d.iteritems():
        if isinstance(value, dict):
            print '\t' * indent + (("%30s: {\n") % str(key).upper())
            pretty(value, indent+1)
            print '\t' * indent + ' ' * 32 + ('} # end of %s #\n' % str(key).upper())
        Elif isinstance(value, list):
            for val in value:
                print '\t' * indent + (("%30s: [\n") % str(key).upper())
                pretty(val, indent+1)
                print '\t' * indent + ' ' * 32 + ('] # end of %s #\n' % str(key).upper())
        else:
            print '\t' * indent + (("%30s: %s") % (str(key).upper(),str(value)))
1
VindeX

Ich habe diesen einfachen Code geschrieben, um die allgemeine Struktur eines Json-Objekts in Python zu drucken. 

def getstructure(data, tab = 0):
    if type(data) is dict:
        print ' '*tab + '{' 
        for key in data:
            print ' '*tab + '  ' + key + ':'
            getstructure(data[key], tab+4)
        print ' '*tab + '}'         
    Elif type(data) is list and len(data) > 0:
        print ' '*tab + '['
        getstructure(data[0], tab+4)
        print ' '*tab + '  ...'
        print ' '*tab + ']'

das Ergebnis für die folgenden Daten

a = {'list':['a','b',1,2],'dict':{'a':1,2:'b'},'Tuple':('a','b',1,2),'function':'p','unicode':u'\xa7',("Tuple","key"):"valid"}
getstructure(a)

ist sehr kompakt und sieht so aus:

{
  function:
  Tuple:
  list:
    [
      ...
    ]
  dict:
    {
      a:
      2:
    }
  unicode:
  ('Tuple', 'key'):
}
1
Abtin Rasoulian

auf diese Weise können Sie es auf hübsche Weise drucken, zum Beispiel, Ihr Wörterbuchname ist yasin

import json

print (json.dumps(yasin, indent=2))
1
yasin lachini

Von diesem Link :

def prnDict(aDict, br='\n', html=0,
            keyAlign='l',   sortKey=0,
            keyPrefix='',   keySuffix='',
            valuePrefix='', valueSuffix='',
            leftMargin=0,   indent=1 ):
    '''
return a string representive of aDict in the following format:
    {
     key1: value1,
     key2: value2,
     ...
     }

Spaces will be added to the keys to make them have same width.

sortKey: set to 1 if want keys sorted;
keyAlign: either 'l' or 'r', for left, right align, respectively.
keyPrefix, keySuffix, valuePrefix, valueSuffix: The prefix and
   suffix to wrap the keys or values. Good for formatting them
   for html document(for example, keyPrefix='<b>', keySuffix='</b>'). 
   Note: The keys will be padded with spaces to have them
         equally-wide. The pre- and suffix will be added OUTSIDE
         the entire width.
html: if set to 1, all spaces will be replaced with '&nbsp;', and
      the entire output will be wrapped with '<code>' and '</code>'.
br: determine the carriage return. If html, it is suggested to set
    br to '<br>'. If you want the html source code eazy to read,
    set br to '<br>\n'

version: 04b52
author : Runsun Pan
require: odict() # an ordered dict, if you want the keys sorted.
         Dave Benjamin 
         http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/161403
    '''

    if aDict:

        #------------------------------ sort key
        if sortKey:
            dic = aDict.copy()
            keys = dic.keys()
            keys.sort()
            aDict = odict()
            for k in keys:
                aDict[k] = dic[k]

        #------------------- wrap keys with ' ' (quotes) if str
        tmp = ['{']
        ks = [type(x)==str and "'%s'"%x or x for x in aDict.keys()]

        #------------------- wrap values with ' ' (quotes) if str
        vs = [type(x)==str and "'%s'"%x or x for x in aDict.values()] 

        maxKeyLen = max([len(str(x)) for x in ks])

        for i in range(len(ks)):

            #-------------------------- Adjust key width
            k = {1            : str(ks[i]).ljust(maxKeyLen),
                 keyAlign=='r': str(ks[i]).rjust(maxKeyLen) }[1]

            v = vs[i]        
            tmp.append(' '* indent+ '%s%s%s:%s%s%s,' %(
                        keyPrefix, k, keySuffix,
                        valuePrefix,v,valueSuffix))

        tmp[-1] = tmp[-1][:-1] # remove the ',' in the last item
        tmp.append('}')

        if leftMargin:
          tmp = [ ' '*leftMargin + x for x in tmp ]

        if html:
            return '<code>%s</code>' %br.join(tmp).replace(' ','&nbsp;')
        else:
            return br.join(tmp)     
    else:
        return '{}'

'''
Example:

>>> a={'C': 2, 'B': 1, 'E': 4, (3, 5): 0}

>>> print prnDict(a)
{
 'C'   :2,
 'B'   :1,
 'E'   :4,
 (3, 5):0
}

>>> print prnDict(a, sortKey=1)
{
 'B'   :1,
 'C'   :2,
 'E'   :4,
 (3, 5):0
}

>>> print prnDict(a, keyPrefix="<b>", keySuffix="</b>")
{
 <b>'C'   </b>:2,
 <b>'B'   </b>:1,
 <b>'E'   </b>:4,
 <b>(3, 5)</b>:0
}

>>> print prnDict(a, html=1)
<code>{
&nbsp;'C'&nbsp;&nbsp;&nbsp;:2,
&nbsp;'B'&nbsp;&nbsp;&nbsp;:1,
&nbsp;'E'&nbsp;&nbsp;&nbsp;:4,
&nbsp;(3,&nbsp;5):0
}</code>

>>> b={'car': [6, 6, 12], 'about': [15, 9, 6], 'bookKeeper': [9, 9, 15]}

>>> print prnDict(b, sortKey=1)
{
 'about'     :[15, 9, 6],
 'bookKeeper':[9, 9, 15],
 'car'       :[6, 6, 12]
}

>>> print prnDict(b, keyAlign="r")
{
        'car':[6, 6, 12],
      'about':[15, 9, 6],
 'bookKeeper':[9, 9, 15]
}
'''
0
user2757572

Verwenden Sie diese Funktion:

def pretty_dict(d, n=1):
    for k in d:
        print(" "*n + k)
        try:
            pretty_dict(d[k], n=n+4)
        except TypeError:
            continue

Nenne es so:

pretty_dict(mydict)
0
fiftytwocards

Hier ist etwas, das jede Art von verschachteltem Wörterbuch druckt und dabei die "übergeordneten" Wörterbücher auf dem Weg nachverfolgt. 

dicList = list()

def prettierPrint(dic, dicList):
count = 0
for key, value in dic.iteritems():
    count+=1
    if str(value) == 'OrderedDict()':
        value = None
    if not isinstance(value, dict):
        print str(key) + ": " + str(value)
        print str(key) + ' was found in the following path:',
        print dicList
        print '\n'
    Elif isinstance(value, dict):
        dicList.append(key)
        prettierPrint(value, dicList)
    if dicList:
         if count == len(dic):
             dicList.pop()
             count = 0

prettierPrint(dicExample, dicList)

Dies ist ein guter Ausgangspunkt für das Drucken in verschiedenen Formaten, wie dem in OP angegebenen. Alles was Sie wirklich tun müssen, ist Operationen um die Blöcke Print herum. Beachten Sie, dass der Wert 'OrderedDict ()' lautet. Abhängig davon, ob Sie etwas von Container-Datentypen Collections verwenden, sollten Sie diese Art von Fail-Safes machen, damit der Elif -Block ihn nicht aufgrund seines Namens als zusätzliches Wörterbuch erkennt. Ab sofort ist ein Beispielwörterbuch wie 

example_dict = {'key1': 'value1',
            'key2': 'value2',
            'key3': {'key3a': 'value3a'},
            'key4': {'key4a': {'key4aa': 'value4aa',
                               'key4ab': 'value4ab',
                               'key4ac': 'value4ac'},
                     'key4b': 'value4b'}

wird drucken

key3a: value3a
key3a was found in the following path: ['key3']

key2: value2
key2 was found in the following path: []

key1: value1
key1 was found in the following path: []

key4ab: value4ab
key4ab was found in the following path: ['key4', 'key4a']

key4ac: value4ac
key4ac was found in the following path: ['key4', 'key4a']

key4aa: value4aa
key4aa was found in the following path: ['key4', 'key4a']

key4b: value4b
key4b was found in the following path: ['key4']

~ Ändern des Codes an das Format der Frage ~

lastDict = list()
dicList = list()
def prettierPrint(dic, dicList):
    global lastDict
    count = 0
    for key, value in dic.iteritems():
        count+=1
        if str(value) == 'OrderedDict()':
            value = None
        if not isinstance(value, dict):
            if lastDict == dicList:
                sameParents = True
            else:
                sameParents = False

            if dicList and sameParents is not True:
                spacing = ' ' * len(str(dicList))
                print dicList
                print spacing,
                print str(value)

            if dicList and sameParents is True:
                print spacing,
                print str(value)
            lastDict = list(dicList)

        Elif isinstance(value, dict):
            dicList.append(key)
            prettierPrint(value, dicList)

        if dicList:
             if count == len(dic):
                 dicList.pop()
                 count = 0

Mit demselben Beispielcode wird Folgendes gedruckt: 

['key3']
         value3a
['key4', 'key4a']
                  value4ab
                  value4ac
                  value4aa
['key4']
         value4b

Dies ist nicht genau was im OP angefordert wird. Der Unterschied ist, dass ein Elternteil noch gedruckt wird, anstatt abwesend zu sein und durch Leerzeichen ersetzt zu werden. Um zum OP-Format zu gelangen, müssen Sie Folgendes tun: Vergleichen Sie dicList iterativ mit lastDict. Sie können dies tun, indem Sie ein neues Wörterbuch erstellen und den Inhalt von dicList in das Wörterbuch kopieren. Prüfen Sie, ob i im kopierten Wörterbuch mit i in lastDict übereinstimmt, und, wenn dies der Fall ist, Leerzeichen schreiben diese i Position unter Verwendung der String-Multiplikatorfunktion.

0
gavin

Ich komme gerade zu dieser Frage zurück, nachdem ich sth s Antwort genommen und eine kleine, aber sehr nützliche Änderung vorgenommen hatte. Diese Funktion druckt alle -Schlüssel im JSON-Baum sowie die -Größe der Blattknoten in diesem Baum.

def print_JSON_tree(d, indent=0):
    for key, value in d.iteritems():
        print '    ' * indent + unicode(key),
        if isinstance(value, dict):
            print; print_JSON_tree(value, indent+1)
        else:
            print ":", str(type(d[key])).split("'")[1], "-", str(len(unicode(d[key])))

Es ist wirklich schön, wenn Sie große JSON-Objekte haben und herausfinden möchten, wo sich das Fleisch befindet. Beispiel:

>>> print_JSON_tree(JSON_object)
key1
    value1 : int - 5
    value2 : str - 16
    key2
       value1 : str - 34
       value2 : list - 5623456

Dies würde Ihnen sagen, dass sich die meisten Daten, die Sie interessieren, wahrscheinlich in JSON_object['key1']['key2']['value2'] befinden, da die Länge dieses als Zeichenfolge formatierten Werts sehr groß ist.

0
Ulf Aslak