2010-11-29 121 views
80

我喜歡Python中的pprint模塊。我用它進行測試和調試。我經常使用寬度選項來確保輸出很好地適合我的終端窗口。任何正確漂亮打印有序字典的方法?

它工作得很好,直到他們在Python 2.7中添加了新的ordered dictionary type(我真的很喜歡另一個很酷的功能)。如果我試圖漂亮地打印有序字典,它不會很好地顯示。而不是讓每一個鍵值對自己行,整個事情就會出現在一條長長的行上,這個行很多次,很難閱讀。

有沒有人有辦法讓它打印很好,就像舊的無序字典一樣?如果我花了足夠的時間,我可能會想出一些東西,可能使用PrettyPrinter.format方法,但我想知道是否有人在這裏已經知道解決方案。

更新:我爲此提交了一個錯誤報告。你可以在http://bugs.python.org/issue10592看到它。

+6

可能要考慮打開一個bug。 – 2010-11-29 05:29:59

+0

我正在考慮這樣做。我會在這裏發佈更新,如果我這樣做。 – 2010-11-29 05:36:13

+1

建議添加有關有序字典的評論到http://bugs.python.org/issue7434 – 2010-11-29 08:51:32

回答

2
def pprint_od(od): 
    print "{" 
    for key in od: 
     print "%s:%s,\n" % (key, od[key]) # Fixed syntax 
    print "}" 

你去那裏^^

for item in li: 
    pprint_od(item) 

(pprint_od(item) for item in li) 
+0

我正在尋找一種方法來有一個功能,可以漂亮地打印OrderedDicts以及其他類型。我沒有看到我將如何使用你的函數來漂亮地打印OrderedDicts列表。 – 2010-11-29 05:38:53

+0

讓我對它進行修改 – 2010-11-29 05:40:52

+0

-1'pprint_od()`函數不起作用 - 對於key中的項,od語句中的項產生'ValueError:太多的值來解壓縮*和*唯一的輸出是縮進的在`print`語句中最後的``}「`*和*`key,item`需要在括號中。你去了^^ – martineau 2010-11-29 09:33:14

10

下面的工作,如果你的OrderedDict的順序是字母排序,因爲pprint將整理打印前的字典。

pprint(dict(o.items())) 
+2

由於OrderedDicts按插入順序排序,所以這可能適用於一小部分使用。無論如何,將OD轉換爲「dict」應該避免將所有內容放在一行上。 – martineau 2010-11-29 09:07:51

0

你可以重新定義爲OrderedDictpprint()和攔截來電。這是一個簡單的例子。如所寫的,OrderedDict覆蓋代碼忽略任何可能已經通過但可以增強以實現它們的可選streamindent,widthdepth關鍵字。但這種方法不處理他們另一個容器內,比如一個listOrderDict

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 
# } 
8

下面是通過覆蓋和使用內部股票pprint()功能中的另一種答案。不像我的earlier one處理OrderedDict的另一個容器,如list的內部,並且還應該能夠處理給定的任何可選關鍵字參數 - 但它沒有控制另一個輸出提供的輸出相同程度的控制。

它通過將庫存函數的輸出重定向到一個臨時緩衝區進行操作,然後在將它發送到輸出流之前將其換行。雖然最終產出並不是特別漂亮,但它很體面,可能「足夠好」可以用作解決方法。

更新2.0

通過使用標準庫textwrap模塊簡化,並且修改 Python 2中& 3兩者工作。

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

輸出示例:

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

104

作爲臨時解決方法,您可以嘗試以JSON格式進行轉儲。 你失去了一些類型的信息,但它看起來不錯,並保持秩序。

import json 

pprint(data, indent=4) 
# ^ugly 

print(json.dumps(data, indent=4)) 
# ^nice 
1

pprint()方法只是調用的東西__repr__()方法在裏面,OrderedDict似乎沒有做太多在它的方法(或不具有一個或某事)。

這裏是一個廉價的解決方案,應該工作如果你不關心排列順序爲可見的PPRINT輸出,這可能是一個很大的,如果:

class PrintableOrderedDict(OrderedDict): 
    def __repr__(self): 
     return dict.__repr__(self) 

實際上,我驚訝的是,訂單沒有保存好啊。

0

如果字典項都是一個類型的,你可以用驚人的數據處理庫pandas

>>> import pandas as pd 
>>> x = {'foo':1, 'bar':2} 
>>> pd.Series(x) 
bar 2 
foo 1 
dtype: int64 

>>> import pandas as pd 
>>> x = {'foo':'bar', 'baz':'bam'} 
>>> pd.Series(x) 
baz bam 
foo bar 
dtype: object 
2

這是相當粗糙的,但我只是需要一個方式來可視化由任意映射和Iterables組成的數據結構,這就是我在放棄之前想出的。它是遞歸的,所以它將會通過嵌套結構和列表來處理。我使用集合中的Mapping和Iterable抽象基類來處理任何事情。

我的目標是幾乎像yaml一樣用簡潔的python代碼輸出,但並沒有完全實現。

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 

,並使用OrderedDict和OrderedDicts的列出了一些測試數據...(嘖Python的需要OrderedDict文字SOOO不好...)

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) 

產生以下的輸出:

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 

我一起使用以便更好地對齊str.format()的方法的一些想法,但是不喜歡挖進去。您需要動態指定字段寬度,具體取決於您想要的對齊類型,這會變得棘手或麻煩。

無論如何,這表明我的數據以可讀的層次結構方式顯示,因此適用於我!

7

要打印有序的字典,例如

from collections import OrderedDict 

d=OrderedDict([ 
    ('a', OrderedDict([ 
     ('a1',1), 
     ('a2','sss') 
    ])), 
    ('b', OrderedDict([ 
     ('b1', OrderedDict([ 
      ('bb1',1), 
      ('bb2',4.5)])), 
     ('b2',4.5) 
    ])), 
]) 

我做

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) 

其中產量

"a": { 
    "a1": 1, 
    "a2": "sss" 
}, 
"b": { 
    "b1": { 
     "bb1": 1, 
     "bb2": 4.5 
    }, 
    "b2": 4.5 
} 

print dict_or_OrdDict_to_formatted_str(d, mode='OD') 

這將產生

("a", OrderedDict([ 
    ("a1", 1), 
    ("a2", "sss") 
])), 
("b", OrderedDict([ 
    ("b1", OrderedDict([ 
     ("bb1", 1), 
     ("bb2", 4.5) 
    ])), 
    ("b2", 4.5) 
])) 
4

這是一種破解pprint實施的方法。 pprint在打印之前對鍵進行排序,所以爲了保持順序,我們只需要按照我們想要的方式排序鍵。

請注意,這會影響items()函數。 因此,您可能想要在執行pprint後保留並恢復重寫的函數。

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'} 
-1

您也可以使用這種簡化的kzh答案:

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

它保留了訂單,將輸出幾乎比webwurst答案(打印通過JSON傾倒)相同。