順序付けられた辞書を適切にきれいに印刷する方法はありますか?


97

Pythonのpprintモジュールが好きです。私はテストとデバッグのためにそれをたくさん使います。幅オプションを頻繁に使用して、出力が端末ウィンドウ内にうまく収まるようにします。

彼らがPython 2.7で新しい順序付けられた辞書タイプを追加するまでは、うまく機能しました(私が本当に気に入っているもう1つのクールな機能)。順序付けされた辞書をきれいに印刷しようとすると、うまく表示されません。キーと値の各ペアを1行に記述するのではなく、全体が1つの長い行に表示されるため、何度も折り返されて読みづらくなります。

古い順不同の辞書のように、ここに誰かがきれいに印刷する方法を持っていますか?十分な時間を費やせば、おそらくPrettyPrinter.formatメソッドを使用して何かを理解できるでしょうが、ここにいる誰かがすでに解決策を知っているかどうか疑問に思っています。

更新:これについてバグレポートを提出しました。http://bugs.python.org/issue10592で確認できます。


2
順序付けられた辞書に関するコメントをbugs.python.org/issue7434に
Ned Deily 2010年

回答:


131

一時的な回避策として、JSON形式でダンプを試すことができます。一部のタイプ情報は失われますが、見た目がよく、順序は保持されます。

import json

pprint(data, indent=4)
# ^ugly

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

7
@scottmrogowskiなぜ単純ではないのですpprint.pprint(dict(data))か?
Alfe、2015

2
pprint.pprint(dict(data))キーの順序を気にしない場合はうまく機能します。個人的には、__repr__for OrderedDictがこのような出力を生成することを望みますが、キーの順序は保持します。
ws_e_c421 2015

9
@Alfe dictにOrderedDictsがネストされている場合、うまく表示されません
Catskul

1
また、キーとしての整数では失敗します
DimmuR '19 / 07/19

2
@Alfe:出力が順序付けされていないため。そもそもdictの代わりにOrderedDictを使用するのは、順序が重要だからです。
Teekin 2018

15

pprintは印刷前にdictをソートするため、OrderedDictの順序がアルファソートの場合、以下が機能します。

pprint(dict(o.items()))

2
OrderedDictsは挿入順に並べ替えられるため、これはおそらく使用のごく一部に当てはまります。とにかく、ODをaに変換することで、dictすべてが1行に配置される問題を回避できます。
martineau

8

これは、ストックpprint()関数を内部的にオーバーライドして使用することで機能する別の答えです。私とは違って、以前の1、それはなりますハンドルOrderedDictのような別の容器内のをlistしても、与えられた任意のオプションのキーワード引数を処理できる必要があります-しかし、それは他の1が与えられることに出力を制御の同じ学位を持っていません。

これは、ストック関数の出力を一時バッファーにリダイレクトし、それを出力ストリームに送信する前にワードラップして動作します。生成される最終出力は例外的にきれいではありませんが、まともであり、回避策として使用するには「十分」である可能性があります。

アップデート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)])]


私はそれを試してみましたが、うまくいきました。あなたが言ったように、それはきれいではありませんが、私が今まで見た中で最高の解決策です。
エリアスザマリア

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

5

の実装をハッキングする方法を次に示しますpprintpprint印刷前にキーを並べ替えるので、順序を維持するには、キーを希望どおりに並べ替える必要があります。

これは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'}

2
いいですが、サブタイプを使用して関数をオーバーライドする方が適切です。
xmedeko 2017年

3

OrderedDictをきれいに印刷するための私のアプローチは次のとおりです

from collections import OrderedDict
import json
d = OrderedDict()
d['duck'] = 'alive'
d['parrot'] = 'dead'
d['penguin'] = 'exploded'
d['Falcon'] = 'discharged'
print(d)
print(json.dumps(d,indent=4))

OutPut:

OrderedDict([('duck', 'alive'), ('parrot', 'dead'), ('penguin', 'exploded'), ('Falcon', 'discharged')])

{
    "duck": "alive",
    "parrot": "dead",
    "penguin": "exploded",
    "Falcon": "discharged"
}

キーを並べ替えた辞書をきれいに印刷したい場合

print(json.dumps(indent=4,sort_keys=True))
{
    "Falcon": "discharged",
    "duck": "alive",
    "parrot": "dead",
    "penguin": "exploded"
}

@AlxVallejoを使用してpython3いる可能性があります。確認してください
CHINTAN VADGAMA

2

これはかなり大雑把ですが、任意のマッピングとイテラブルで構成されたデータ構造を視覚化する方法が必要であり、これはあきらめる前に思いついたものです。これは再帰的であるため、ネストされた構造とリストをうまく通過します。コレクションのMappingおよびIterable抽象基本クラスを使用して、ほぼすべてを処理しました。

私は簡潔なpythonコードで出力のようにほぼyamlを目指していましたが、うまくいきませんでした。

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のリストを使用したいくつかのテストデータ...(sheesh PythonにはOrderedDictリテラルが必要です...)

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()を使用して位置合わせを改善する方法についていくつか考えましたが、それを掘り下げる気にはなりませんでした。必要な配置のタイプに応じてフィールド幅を動的に指定する必要がありますが、これはトリッキーまたは扱いにくいものになります。

とにかく、これは私のデータを読みやすい階層形式で示しているので、それは私にとってうまくいきます!


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)

OrderedDictsやその他の型をきれいに出力できる1つの関数を作成する方法を探しています。OrderedDictsのリストをきれいに出力するために関数をどのように使用するかわかりません。
エリアスザマリア

-1 pprint_od()-機能が働かないfor key, item in odで文の結果ValueError: too many values to unpack 最終的なものでインデントのみを出力" }" し、key, itemprint括弧内になるように文の必要性を。^^
martineau

2

私はpython3.5でこの不気味なモンキーパッチベースのハックをテストしましたが、うまくいきました:

pprint.PrettyPrinter._dispatch[pprint._collections.OrderedDict.__repr__] = pprint.PrettyPrinter._pprint_dict


def unsorted_pprint(data):
    def fake_sort(*args, **kwargs):
        return args[0]
    orig_sorted = __builtins__.sorted
    try:
        __builtins__.sorted = fake_sort
        pprint.pprint(data)
    finally:
        __builtins__.sorted = orig_sorted

あなたは作るpprint何のキーが実際に印刷するためにソートされないように、コールの期間中、通常の辞書ベースの要約とも無効にソートを使用します。


pretty_print.pyローカルモジュールとしてコピーし、ハッキングすることsortedもできます(呼び出しまたは必要なものを削除)。
Karl Rosaen

2

Python 3.8以降:キーワードパラメータをpprint.PrettyPrinter公開しsort_dictsます。

デフォルトではTrueFalseに設定すると辞書はソートされません。

>>> from pprint import PrettyPrinter

>>> x = {'John': 1,
>>>      'Mary': 2,
>>>      'Paul': 3,
>>>      'Lisa': 4,
>>>      }

>>> PrettyPrinter(sort_dicts=False).pprint(x)

出力されます:

{'John': 1, 
 'Mary': 2, 
 'Paul': 3,
 'Lisa': 4}

リファレンス:https : //docs.python.org/3/library/pprint.html


1

pprint()この方法はただ呼び出している__repr__()ことで物事の方法を、およびOrderedDictそれの方法(または1か何かを持っていない)に多くを行うには表示されません。

ここでは、印刷出力で表示される注文を気にしない場合に機能する安価なソリューションを示します。

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

注文が保存されていないことに驚いています...


Python辞書は、ハッシュマップを使用して実装されます。したがって、OrderedDict(基本的な辞書と順序を保持するためのリストの組み合わせ)を辞書に変換すると、注文情報は失われます。さらに、reprメソッドは、Pythonコードでオブジェクトを表す文字列を返すことになっています。つまり、obj == eval(repr(obj))、または少なくともrepr(obj)== repr(eval(repr(obj)))です。OrderedDictのreprはこれをうまく実行します。dict .__ repr__が非常に人間が読める表現を提供することは、完全にdictリテラル(「{」や「}」など)の副作用です。OrderedDictにはこれがありません。
marr75


1

Python 3.8未満(例:3.6):

モンキーパッチはpprint「S sorted並べ替えからそれを防ぐために。これはすべてが再帰的に機能するという利点があり、jsonたとえばwidthパラメータを使用する必要がある人のためのオプションよりも適しています。

import pprint
pprint.sorted = lambda arg, *a, **kw: arg

>>> pprint.pprint({'z': 1, 'a': 2, 'c': {'z': 0, 'a': 1}}, width=20)
{'z': 1,
 'a': 2,
 'c': {'z': 0,
       'a': 1}}

編集:クリーンアップ

この汚いビジネスの後にクリーンアップするには、次のコマンドを実行します。 pprint.sorted = sorted

本当にクリーンなソリューションの場合は、contextmanagerを使用することもできます。

import pprint
import contextlib

@contextlib.contextmanager
def pprint_ordered():
    pprint.sorted = lambda arg, *args, **kwargs: arg
    yield
    pprint.sorted = sorted

# usage:

with pprint_ordered():
    pprint.pprint({'z': 1, 'a': 2, 'c': {'z': 0, 'a': 1}}, width=20)

# without it    
pprint.pprint({'z': 1, 'a': 2, 'c': {'z': 0, 'a': 1}}, width=20)

# prints: 
#    
# {'z': 1,
#  'a': 2,
#  'c': {'z': 0,
#        'a': 1}}
#
# {'a': 2,
#  'c': {'a': 1,
#        'z': 0},
#  'z': 1}

0

pprint()呼び出しを再定義してインターセプトできOrderedDictます。これが簡単なイラストです。書かれているように、OrderedDictオーバーライドコードは、任意のオプションは無視されstreamindentwidth、またはdepth渡されているかもしれないが、それらを実装するように拡張することができ、キーワードを。残念ながら、この技術は、次のような、別の容器内でそれらを処理しない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
# }

0

辞書のアイテムがすべて1つのタイプである場合、すばらしいデータ処理ライブラリを使用できます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
そのコードは何をしますか?ここで他のソリューションよりも優れている点は何ですか?
エリアスザマリア2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.