Comment puis-je imprimer un dictionnaire avec une profondeur de ~ 4 en Python? J'ai essayé de jolies impressions avec pprint()
, mais cela n'a pas fonctionné:
import pprint
pp = pprint.PrettyPrinter(indent=4)
pp.pprint(mydict)
Je veux simplement une indentation ("\t"
) pour chaque imbrication, afin d'obtenir quelque chose comme ceci:
key1
value1
value2
key2
value1
value2
etc.
Comment puis-je faire ceci?
Je ne sais pas à quoi ressemble exactement le formatage, mais vous pourriez commencer par une fonction comme celle-ci:
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))
( pour l'utilisateur python 2: importer la fonction d'impression de __future__ )
Ma première pensée a été que le sérialiseur JSON est probablement assez bon pour les dictionnaires imbriqués, alors je tricherais et utiliserais ça:
>>> 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
}
}
}
Vous pouvez essayer YAML via PyYAML . Sa sortie peut être ajustée. Je suggère de commencer par ce qui suit:
print yaml.dump(data, allow_unicode=True, default_flow_style=False)
Le résultat est très lisible; il peut également être analysé dans Python si nécessaire.
Modifier:
Exemple:
>>> 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
En ce qui concerne ce qui a été fait, je ne vois pas de jolie imprimante qui imite au moins la sortie de l'interpréteur Python avec un formatage très simple, alors voici le mien:
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)
Pour l'initialiser:
pretty = Formatter()
Il peut prendre en charge l’ajout de formateurs pour des types définis. Vous devez simplement créer une fonction semblable à celle-ci et la lier au type souhaité avec set_formater:
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)
Pour des raisons historiques, je conserve la jolie imprimante précédente qui était une fonction au lieu d'une classe, mais elles peuvent toutes deux être utilisées de la même manière, la version de la classe autorisant simplement beaucoup plus:
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)
Pour l'utiliser :
>>> 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'
}
Par rapport aux autres versions:
Une autre option avec 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)
Sortie:
{
'1': '1',
'2': '2',
'3': [1, 2, 3, 4, 5],
'4': {
'1': '1',
'2': '2',
'3': [1, 2, 3, 4, 5]
}
}
J'ai pris la réponse de sth et l'ai légèrement modifiée pour répondre à mes besoins de dictionnaires et de listes imbriquées:
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
Ce qui me donne alors une sortie comme:
>>>
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
...
Comme d'autres l'ont écrit, vous pouvez utiliser récursivité/dfs pour imprimer les données de dictionnaire imbriquées et les appeler récursivement s'il s'agit d'un dictionnaire; sinon, imprimez les données.
def print_json(data):
if type(data) == dict:
for k, v in data.items():
print k
print_json(v)
else:
print data
pout peut très bien imprimer tout ce que vous lui lancez, par exemple (emprunter data
d'une autre réponse):
data = {'a':2, 'b':{'x':3, 'y':{'t1': 4, 't2':5}}}
pout.vs(data)
entraînerait une sortie imprimée à l’écran comme:
{
'a': 2,
'b':
{
'y':
{
't2': 5,
't1': 4
},
'x': 3
}
}
ou vous pouvez renvoyer la sortie chaîne formatée de votre objet:
v = pout.s(data)
Son principal cas d'utilisation est le débogage afin d'éviter toute surcharge d'instances d'objet et de gérer la sortie unicode comme vous le souhaiteriez, fonctionne en python 2.7 et 3.
Disclosure: Je suis l'auteur et le responsable de la moue.
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)
Sth, je coule c'est joli;)
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)))
J'ai écrit ce code simple pour imprimer la structure générale d'un objet JSON en Python.
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 + ']'
le résultat pour les données suivantes
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)
est très compact et ressemble à ceci:
{
function:
Tuple:
list:
[
...
]
dict:
{
a:
2:
}
unicode:
('Tuple', 'key'):
}
de cette façon, vous pouvez l’imprimer de façon jolie, par exemple le nom de votre dictionnaire est yasin
import json
print (json.dumps(yasin, indent=2))
De ce lien :
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 ' ', 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(' ',' ')
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>{
'C' :2,
'B' :1,
'E' :4,
(3, 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]
}
'''
Utilisez cette fonction:
def pretty_dict(d, n=1):
for k in d:
print(" "*n + k)
try:
pretty_dict(d[k], n=n+4)
except TypeError:
continue
Appelez ça comme ça:
pretty_dict(mydict)
Voici quelque chose qui imprimera toute sorte de dictionnaire imbriqué, tout en gardant une trace des dictionnaires "parents" tout au long du chemin.
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)
C’est un bon point de départ pour imprimer selon différents formats, comme celui spécifié dans OP. Tout ce que vous avez vraiment besoin de faire est d’effectuer des opérations autour des blocs Print. Notez qu'il semble voir si la valeur est 'OrderedDict ()'. Selon que vous utilisiez quelque chose de Types de données de conteneur Collections , vous devez créer ce type de sécurité intégrée afin que le bloc Elif ne le considère pas comme un dictionnaire supplémentaire en raison de son nom. A partir de maintenant, un exemple de dictionnaire comme
example_dict = {'key1': 'value1',
'key2': 'value2',
'key3': {'key3a': 'value3a'},
'key4': {'key4a': {'key4aa': 'value4aa',
'key4ab': 'value4ab',
'key4ac': 'value4ac'},
'key4b': 'value4b'}
imprimera
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']
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
En utilisant le même exemple de code, il imprimera ce qui suit:
['key3']
value3a
['key4', 'key4a']
value4ab
value4ac
value4aa
['key4']
value4b
Ce n'est pas exactement ce qui est demandé dans OP. La différence est qu'un parent ^ n est toujours imprimé, au lieu d'être absent et remplacé par un espace blanc. Pour obtenir le format OP, vous devez procéder comme suit: comparez de manière itérative dicList avec le lastDict. Vous pouvez le faire en créant un nouveau dictionnaire et en y copiant le contenu de dicList, en vérifiant si i dans le dictionnaire copié est identique à i dans lastDict et, le cas échéant, - écrire des espaces à cette position i en utilisant la fonction multiplicateur de chaîne.
Je reviens à cette question après avoir pris la réponse de sth et apporté une modification petite mais très utile. Cette fonction imprime toutes les clés de l’arbre JSON ainsi que la taille des noeuds feuille de cet arbre.
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])))
C'est vraiment agréable quand vous avez de gros objets JSON et que vous voulez savoir où se trouve la viande. Exemple:
>>> print_JSON_tree(JSON_object)
key1
value1 : int - 5
value2 : str - 16
key2
value1 : str - 34
value2 : list - 5623456
Cela vous indiquerait que la plupart des données qui vous intéressent se trouvent probablement dans JSON_object['key1']['key2']['value2']
car la longueur de cette valeur sous forme de chaîne est très grande.