Python bonito diccionario de impresión de listas, abreviados listas largas

Tengo un diccionario de listas y las listas son bastante largas. ¿Cómo puedo imprimirlo de forma que solo aparezcan algunos elementos de la lista? Obviamente, puedo escribir una función personalizada para eso, pero ¿hay alguna forma integrada o biblioteca que pueda lograr esto? Por ejemplo, cuando imprime grandes marcos de datos, los pandas imprimen muy bien de manera breve.

Este ejemplo ilustra mejor lo que quiero decir:

 obj = {'key_1': ['EG8XYD9FVN', 'S2WARDCVAO', 'J00YCU55DP', 'R07BUIF2F7', 'VGPS1JD0UM', 'WL3TWSDP8E', 'LD8QY7DMJ3', 'J36U3Z9KOQ', 'KU2FUGYB2U', 'JF3RQ315BY'], 'key_2': ['162LO154PM', '3ROAV881V2', 'I4T79LP18J', 'WBD36EM6QL', 'DEIODVQU46', 'KWSJA5WDKQ', 'WX9SVRFO0G', '6UN63WU64G', '3Z89U7XM60', '167CYON6YN']} 

Salida deseada: algo como esto:

 {'key_1': ['EG8XYD9FVN', 'S2WARDCVAO', '...'], 'key_2': ['162LO154PM', '3ROAV881V2', '...'] } 

Si no fuera por la impresión bonita, el módulo de reprlib sería el camino a seguir: el manejo seguro, elegante y personalizable de estructuras de datos profundamente anidadas y recursivas / autorreferenciadas es para lo que se ha diseñado.

Sin embargo, resulta que combinar los módulos reprlib y pprint no es trivial, al menos no pude encontrar una manera limpia sin romper (algunos) los aspectos de impresión bonitos.

Entonces, en lugar de eso, aquí hay una solución que simplemente PrettyPrinter a PrettyPrinter para recortar / abreviar listas según sea necesario:

 from pprint import PrettyPrinter obj = { 'key_1': [ 'EG8XYD9FVN', 'S2WARDCVAO', 'J00YCU55DP', 'R07BUIF2F7', 'VGPS1JD0UM', 'WL3TWSDP8E', 'LD8QY7DMJ3', 'J36U3Z9KOQ', 'KU2FUGYB2U', 'JF3RQ315BY', ], 'key_2': [ '162LO154PM', '3ROAV881V2', 'I4T79LP18J', 'WBD36EM6QL', 'DEIODVQU46', 'KWSJA5WDKQ', 'WX9SVRFO0G', '6UN63WU64G', '3Z89U7XM60', '167CYON6YN', ], # Test case to make sure we didn't break handling of recursive structures 'key_3': [ '162LO154PM', '3ROAV881V2', [1, 2, ['a', 'b', 'c'], 3, 4, 5, 6, 7], 'KWSJA5WDKQ', 'WX9SVRFO0G', '6UN63WU64G', '3Z89U7XM60', '167CYON6YN', ] } class CroppingPrettyPrinter(PrettyPrinter): def __init__(self, *args, **kwargs): self.maxlist = kwargs.pop('maxlist', 6) return PrettyPrinter.__init__(self, *args, **kwargs) def _format(self, obj, stream, indent, allowance, context, level): if isinstance(obj, list): # If object is a list, crop a copy of it according to self.maxlist # and append an ellipsis if len(obj) > self.maxlist: cropped_obj = obj[:self.maxlist] + ['...'] return PrettyPrinter._format( self, cropped_obj, stream, indent, allowance, context, level) # Let the original implementation handle anything else # Note: No use of super() because PrettyPrinter is an old-style class return PrettyPrinter._format( self, obj, stream, indent, allowance, context, level) p = CroppingPrettyPrinter(maxlist=3) p.pprint(obj) 

Salida con maxlist=3 :

 {'key_1': ['EG8XYD9FVN', 'S2WARDCVAO', 'J00YCU55DP', '...'], 'key_2': ['162LO154PM', '3ROAV881V2', [1, 2, ['a', 'b', 'c'], '...'], '...']} 

Salida con maxlist=5 (desencadena la división de las listas en líneas separadas):

 {'key_1': ['EG8XYD9FVN', 'S2WARDCVAO', 'J00YCU55DP', 'R07BUIF2F7', 'VGPS1JD0UM', '...'], 'key_2': ['162LO154PM', '3ROAV881V2', 'I4T79LP18J', 'WBD36EM6QL', 'DEIODVQU46', '...'], 'key_3': ['162LO154PM', '3ROAV881V2', [1, 2, ['a', 'b', 'c'], 3, 4, '...'], 'KWSJA5WDKQ', 'WX9SVRFO0G', '...']} 

Notas:

  • Esto creará copias de las listas. Dependiendo del tamaño de las estructuras de datos, esto puede ser muy costoso en términos de uso de memoria.
  • Esto solo se ocupa del caso especial de listas . Debería implementarse un comportamiento equivalente para los dados, tuplas, conjuntos, frozensets, … para que esta clase sea de uso general.

Podrías usar el módulo pprint :

 pprint.pprint(obj) 

Sería de salida:

 {'key_1': ['EG8XYD9FVN', 'S2WARDCVAO', 'J00YCU55DP', 'R07BUIF2F7', 'VGPS1JD0UM', 'WL3TWSDP8E', 'LD8QY7DMJ3', 'J36U3Z9KOQ', 'KU2FUGYB2U', 'JF3RQ315BY'], 'key_2': ['162LO154PM', '3ROAV881V2', 'I4T79LP18J', 'WBD36EM6QL', 'DEIODVQU46', 'KWSJA5WDKQ', 'WX9SVRFO0G', '6UN63WU64G', '3Z89U7XM60', '167CYON6YN']} 

Y,

 pprint.pprint(obj,depth=1) 

Sería de salida:

 {'key_1': [...], 'key_2': [...]} 

Y,

 pprint.pprint(obj,compact=True) 

saldría:

 {'key_1': ['EG8XYD9FVN', 'S2WARDCVAO', 'J00YCU55DP', 'R07BUIF2F7', 'VGPS1JD0UM', 'WL3TWSDP8E', 'LD8QY7DMJ3', 'J36U3Z9KOQ', 'KU2FUGYB2U', 'JF3RQ315BY'], 'key_2': ['162LO154PM', '3ROAV881V2', 'I4T79LP18J', 'WBD36EM6QL', 'DEIODVQU46', 'KWSJA5WDKQ', 'WX9SVRFO0G', '6UN63WU64G', '3Z89U7XM60', '167CYON6YN']} 

Podría usar IPython.lib.pretty .

 from IPython.lib.pretty import pprint > pprint(obj, max_seq_length=5) {'key_1': ['EG8XYD9FVN', 'S2WARDCVAO', 'J00YCU55DP', 'R07BUIF2F7', 'VGPS1JD0UM', ...], 'key_2': ['162LO154PM', '3ROAV881V2', 'I4T79LP18J', 'WBD36EM6QL', 'DEIODVQU46', ...]} > pprint(dict(map(lambda i: (i, range(i + 5)), range(100))), max_seq_length=10) {0: [0, 1, 2, 3, 4], 1: [0, 1, 2, 3, 4, 5], 2: [0, 1, 2, 3, 4, 5, 6], 3: [0, 1, 2, 3, 4, 5, 6, 7], 4: [0, 1, 2, 3, 4, 5, 6, 7, 8], 5: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 6: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...], 7: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...], 8: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...], 9: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...], ...} 

Para versiones anteriores de IPython, puede explotar RepresentationPrinter :

 from IPython.lib.pretty import RepresentationPrinter import sys def compact_pprint(obj, max_seq_length=10): printer = RepresentationPrinter(sys.stdout) printer.max_seq_length = max_seq_length printer.pretty(obj) printer.flush() 

Esta función recursiva que escribí hace algo que estás pidiendo … También puedes elegir la sangría que quieras

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

La salida de tu diccionario es:

 key_1 ['EG8XYD9FVN', 'S2WARDCVAO', 'J00YCU55DP', 'R07BUIF2F7', 'VGPS1JD0UM', 'WL3TWSDP8E', 'LD8QY7DMJ3', 'J36U3Z9KOQ', 'KU2FUGYB2U', 'JF3RQ315BY'] key_2 ['162LO154PM', '3ROAV881V2', 'I4T79LP18J', 'WBD36EM6QL', 'DEIODVQU46', 'KWSJA5WDKQ', 'WX9SVRFO0G', '6UN63WU64G', '3Z89U7XM60', '167CYON6YN'] 

Utilice reprlib . El formato no es tan bonito, pero en realidad se abrevia.

 > import repr > repr.repr(map(lambda _: range(100000), range(10))) '[[0, 1, 2, 3, 4, 5, ...], [0, 1, 2, 3, 4, 5, ...], [0, 1, 2, 3, 4, 5, ...], [0, 1, 2, 3, 4, 5, ...], [0, 1, 2, 3, 4, 5, ...], [0, 1, 2, 3, 4, 5, ...], ...]' > repr.repr(dict(map(lambda i: (i, range(100000)), range(10)))) '{0: [0, 1, 2, 3, 4, 5, ...], 1: [0, 1, 2, 3, 4, 5, ...], 2: [0, 1, 2, 3, 4, 5, ...], 3: [0, 1, 2, 3, 4, 5, ...], ...}'