pprint – データ構造を見やすい形で出力する

目的:データ構造を見やすい形で出力する
利用できるバージョン:1.4

pprint はデータ構造の表現を見て美しい形で出力する “pretty printer” を提供します。そのフォーマッタはインタープリタが正しく解析したデータ構造の形を生成します。さらにそれは人間にとっても読み易いです。その出力はできるだけ1行でなされ、複数行にわたるときはインデントされます。

全てのサンプルは pprint_data.py に依存しており、そのファイルは次のデータを含んでいます。

data = [ (i, { 'a':'A',
               'b':'B',
               'c':'C',
               'd':'D',
               'e':'E',
               'f':'F',
               'g':'G',
               'h':'H',
               })
         for i in xrange(3)
         ]

表示

このモジュールを使う一番シンプルな方法は pprint() 関数を使うことです。この関数は引数として渡されたオブジェクトを整形して、その内容をデータストリーム(デフォルトでは sys.stdout)へ書き込みます。

from pprint import pprint

from pprint_data import data

print 'PRINT:'
print data
print
print 'PPRINT:'
pprint(data)
$ python pprint_pprint.py
PRINT:
[(0, {'a': 'A', 'c': 'C', 'b': 'B', 'e': 'E', 'd': 'D', 'g': 'G', 'f': 'F', 'h': 'H'}), (1, {'a': 'A', 'c': 'C', 'b': 'B', 'e': 'E', 'd': 'D', 'g': 'G', 'f': 'F', 'h': 'H'}), (2, {'a': 'A', 'c': 'C', 'b': 'B', 'e': 'E', 'd': 'D', 'g': 'G', 'f': 'F', 'h': 'H'})]

PPRINT:
[(0,
  {'a': 'A',
   'b': 'B',
   'c': 'C',
   'd': 'D',
   'e': 'E',
   'f': 'F',
   'g': 'G',
   'h': 'H'}),
 (1,
  {'a': 'A',
   'b': 'B',
   'c': 'C',
   'd': 'D',
   'e': 'E',
   'f': 'F',
   'g': 'G',
   'h': 'H'}),
 (2,
  {'a': 'A',
   'b': 'B',
   'c': 'C',
   'd': 'D',
   'e': 'E',
   'f': 'F',
   'g': 'G',
   'h': 'H'})]

体裁を整える

データ構造の体裁を整える必要があるが、直接ストリームに書き出したくない場合(例えば、ログ目的)、別の関数へ渡せるようにそのデータ構造の文字列表現を組み立てる pformat() を使うことができます。

import logging
from pprint import pformat
from pprint_data import data

logging.basicConfig(level=logging.DEBUG,
                    format='%(levelname)-8s %(message)s',
                    )

logging.debug('Logging pformatted data')
logging.debug(pformat(data))
$ python pprint_pformat.py
DEBUG    Logging pformatted data
DEBUG    [(0,
  {'a': 'A',
   'b': 'B',
   'c': 'C',
   'd': 'D',
   'e': 'E',
   'f': 'F',
   'g': 'G',
   'h': 'H'}),
 (1,
  {'a': 'A',
   'b': 'B',
   'c': 'C',
   'd': 'D',
   'e': 'E',
   'f': 'F',
   'g': 'G',
   'h': 'H'}),
 (2,
  {'a': 'A',
   'b': 'B',
   'c': 'C',
   'd': 'D',
   'e': 'E',
   'f': 'F',
   'g': 'G',
   'h': 'H'})]

任意のクラス

pprint() が使う PrettyPrinter クラスは __repr__() メソッドを定義すれば、独自のクラスと連携することもできます。

from pprint import pprint

class node(object):
    def __init__(self, name, contents=[]):
        self.name = name
        self.contents = contents[:]
    def __repr__(self):
        return 'node(' + repr(self.name) + ', ' + repr(self.contents) + ')'

trees = [ node('node-1'),
         node('node-2', [ node('node-2-1')]),
         node('node-3', [ node('node-3-1')]),
         ]
pprint(trees)
$ python pprint_arbitrary_object.py
[node('node-1', []),
 node('node-2', [node('node-2-1', [])]),
 node('node-3', [node('node-3-1', [])])]

再帰型のデータ

再帰的なデータ構造は <Recursion on typename with id=number> という形式でデータの元のソースへの参照として表現されます。例えば

from pprint import pprint

local_data = [ 'a', 'b', 1, 2 ]
local_data.append(local_data)

print 'id(local_data) =>', id(local_data)
pprint(local_data)
$ python pprint_recursion.py
id(local_data) => 4299545416
['a', 'b', 1, 2, <Recursion on list with id=4299545416>]

入れ子になった出力の制限

とても深い構造を持ったデータに対しては、全ての詳細を出力に含めたくないかもしれません。適切にデータの体裁を整えるのは不可能かもしれないし、体裁を整えた後のテキストデータは管理するには大きすぎるかもしれません。もしくは全ての詳細が必要かもしれません。そういった場合、pretty printer が入れ子になったデータ構造をどのぐらい辿るのかを depth 引数で制御することができます。

from pprint import pprint

from pprint_data import data

pprint(data, depth=1)
$ python pprint_depth.py
[(...), (...), (...)]

出力の幅の設定

体裁を整えたテキストのデフォルト幅は 80 列です。その幅を調整するには pprint() の width 引数を使用してください。

from pprint import pprint

from pprint_data import data

for d in data:
    for c in 'defgh':
        del d[1][c]

for width in [ 80, 20, 5 ]:
    print 'WIDTH =', width
    pprint(data, width=width)
    print

体裁を整えたデータ構造を表示するのにその幅が狭すぎるとき、そのデータ構造が不正な構文であっても、その行が切り捨てられたり、まとめられたりはしないことに注意してください。

$ python pprint_width.py
WIDTH = 80
[(0, {'a': 'A', 'b': 'B', 'c': 'C'}),
 (1, {'a': 'A', 'b': 'B', 'c': 'C'}),
 (2, {'a': 'A', 'b': 'B', 'c': 'C'})]

WIDTH = 20
[(0,
  {'a': 'A',
   'b': 'B',
   'c': 'C'}),
 (1,
  {'a': 'A',
   'b': 'B',
   'c': 'C'}),
 (2,
  {'a': 'A',
   'b': 'B',
   'c': 'C'})]

WIDTH = 5
[(0,
  {'a': 'A',
   'b': 'B',
   'c': 'C'}),
 (1,
  {'a': 'A',
   'b': 'B',
   'c': 'C'}),
 (2,
  {'a': 'A',
   'b': 'B',
   'c': 'C'})]

See also

pprint
本モジュールの標準ライブラリドキュメント
Bookmark and Share