2014-01-29 2 views
0

Я использую pprint, чтобы красиво распечатать dict, и он отлично работает. Теперь я переключаюсь на использование OrderedDict с модуля collections. К сожалению, маршрутизация pprint, похоже, не признает, что такие объекты больше или меньше dict с, и возвращается к печати в виде длинной строки.pretty-printing OrderedDicts using pprint

>>> d = { i:'*'*i for i in range(8) } 
>>> pprint.pprint(d) 
{0: '', 
1: '*', 
2: '**', 
3: '***', 
4: '****', 
5: '*****', 
6: '******', 
7: '*******'} 
>>> pprint.pprint(collections.OrderedDict(d)) 
OrderedDict([(0, ''), (1, '*'), (2, '**'), (3, '***'), (4, '****'), (5, '*****'), (6, '******'), (7, '*******')]) 

Любой путь, чтобы получить более хорошее представление OrderedDict s, а? Может быть, даже если они вложены внутри a нормальный dict или list?

ответ

2

Попробуйте это на:

d = collections.OrderedDict({ i:'*'*i for i in range(8) })

EDIT

pprint.pprint(list(d.items()))

+0

Да, хорошо, ладно. Затем это выглядит как список кортежей, а не как 'dict'. Я надеялся на представление, которое по-прежнему выглядело как дикт (и, возможно, просто проигнорировало тот факт, что это было упорядоченное). – Alfe

+1

Я думаю, вы даже можете разбить «список» вокруг этих 'd.items()'. Но я все еще удивляюсь, почему у 'pprint' даже есть такая проблема с' OrderedDict'; ведь они наследуют 'dict'. – Alfe

+0

Ах, я думал, что это неважно, было ли это в списке на основе «Может быть, даже если они вложены внутри нормального диктата или списка?» – misakm

3

Я нашел довольно простое решение для этого, но она включает в себя риск сделать вывод для вашего упорядоченный словарь выглядит точно так, как если бы это был обычный объект dict.

Исходное решение для использования диспетчера контекста для предотвращения использования pprint от сортировки словарных ключей происходит от this answer.

@contextlib.contextmanager 
def pprint_OrderedDict(): 
    pp_orig = pprint._sorted 
    od_orig = OrderedDict.__repr__ 
    try: 
     pprint._sorted = lambda x:x 
     OrderedDict.__repr__ = dict.__repr__ 
     yield 
    finally: 
     pprint._sorted = pp_orig 
     OrderedDict.__repr__ = od_orig 

(Вы также можете просто залатать метод OrderedDict.__repr__ с dict.__repr__, но, пожалуйста, нет.)

Пример:

>>> foo = [('Roger', 'Owner'), ('Diane', 'Manager'), ('Bob', 'Manager'), 
...  ('Ian', 'Associate'), ('Bill', 'Associate'), ('Melinda', 'Associate')] 

>>> d = OrderedDict(foo) 
>>> pprint.pprint(d) 
OrderedDict([('Roger', 'Owner'), ('Diane', 'Manager'), ('Bob', 'Manager'), ('Ian', 'Associate'), ('Bill', 'Associate'), ('Melinda', 'Associate')]) 

>>> pprint.pprint(dict(d)) 
{'Bill': 'Associate', 
'Bob': 'Manager', 
'Diane': 'Manager', 
'Ian': 'Associate', 
'Melinda': 'Associate', 
'Roger': 'Owner'} 

>>> with pprint_OrderedDict(): 
...  pprint.pprint(d) 
... 
{'Roger': 'Owner', 
'Diane': 'Manager', 
'Bob': 'Manager', 
'Ian': 'Associate', 
'Bill': 'Associate', 
'Melinda': 'Associate'} 
1

Если вы специально нацеленные CPython * 3.6 или более поздней версии, то вы можете just use regular dictionaries вместо OrderedDict. Вы пропустите несколько methods exclusive to OrderedDict, и это еще не гарантировано для переносимости других реализаций на языке Python **, но это, вероятно, самый простой способ выполнить то, что вы пытаетесь сделать.

* CPython - эталонная реализация Python, которая может быть загружена с python.org.
** CPython stole this idea from PyPy, так что вы, вероятно, можете зависеть от того, что он работает там тоже.

+0

Интересно! Но в настоящее время они говорят, что на него нельзя положиться, пока не изменятся спецификации языка, которые могут произойти в будущем. Так хорошо, хм. – Alfe

0

Я понимаю, что это своего рода некропостинг, но я думал, что опубликую то, что я использую. Его основным достоинством является то, что его выход может быть прочитан в python, что позволяет, например, затворить между представлениями (которые я использую, например, в файлах JSON). Конечно, он разрушает инкапсуляцию pprint, вырывая некоторый код из его внутренней функции _format.

#!/bin/env python 
from __future__ import print_function 

import pprint; 
from collections import OrderedDict 
import json 
import sys 


class MyPP (pprint.PrettyPrinter): 
    def _format(self, object, stream, indent, allowance, context, level): 
     if not isinstance(object, OrderedDict) : 
      return pprint.PrettyPrinter._format(self, object, stream, indent, allowance, context, level) 
     level = level + 1 
     objid = id(object) 
     if objid in context: 
      stream.write(_recursion(object)) 
      self._recursive = True 
      self._readable = False 
      return 
     write = stream.write 
     _len=len 
     rep = self._repr(object, context, level - 1) 
     typ = type(object) 
     sepLines = _len(rep) > (self._width - 1 - indent - allowance) 

     if self._depth and level > self._depth: 
      write(rep) 
      return 

     write('OrderedDict([\n%s'%(' '*(indent+1),)) 
     if self._indent_per_level > 1: 
      write((self._indent_per_level - 1) * ' ') 
     length = _len(object) 
     #import pdb; pdb.set_trace() 
     if length: 
      context[objid] = 1 
      indent = indent + self._indent_per_level 
      items = object.items() 
      key, ent = items[0] 
      rep = self._repr(key, context, level) 
      write('(') 
      write(rep) 
      write(', ') 
      self._format(ent, stream, indent + _len(rep) + 2, 
         allowance + 1, context, level) 
      write(')') 
      if length > 1: 
       for key, ent in items[1:]: 
        rep = self._repr(key, context, level) 
        if sepLines: 
         write(',\n%s(%s , ' % (' '*indent, rep)) 
        else: 
         write(', (%s , ' % rep) 
        self._format(ent, stream, indent + _len(rep) + 2, 
           allowance + 1, context, level) 
        write(')') 

      indent = indent - self._indent_per_level 
      del context[objid] 
     write('])') 
     return 

pp = MyPP(indent=1) 
handle=open(sys.argv[1],"r") 
values=json.loads(handle.read(),object_pairs_hook=OrderedDict) 
pp.pprint(values) 
Смежные вопросы