pprintモジュールを使うと、リストや辞書などのオブジェクトを見やすく整形して出力することができます。
組み込み関数のprint()で表示するとデータは1行で出力されるので、見辛いことがあります。そのようなときは標準ライブラリのpprintモジュールを使って見やすく整形して出力します。組み込み関数print()とpprint.pprint()を比べた次の例を見てください。
>>> import pprint >>> animals = ['elephant', 'tiger', 'bear', 'hippopotamus'] >>> fruits = {'strawberry': {'price': 500, 'color': 'red'}, ... 'banana': {'price': 180, 'color': 'yellow'}, ... 'apple': {'price': 120, 'color': 'red'}}
pprintモジュールの読み込みと、表示するデータを準備します。print()関数で表示するとこんな感じです。
>>> print(animals) ['elephant', 'tiger', 'bear', 'hippopotamus'] >>> print(fruits) {'strawberry': {'price': 500, 'color': 'red'}, 'banana': {'price': 180, 'color': 'yellow'}, 'apple': {'price': 120, 'color': 'red'}}
pprint()で表示すると次のようになります。
>>> pprint.pprint(animals, width=40) ['elephant', 'tiger', 'bear', 'hippopotamus'] >>> pprint.pprint(fruits) {'apple': {'color': 'red', 'price': 120}, 'banana': {'color': 'yellow', 'price': 180}, 'strawberry': {'color': 'red', 'price': 500}}
データが複数行に整形されてprint()関数より見やすくなったでしょう。
この記事では整形するデータとして、上述のリストと辞書を使います。しかしpprint()関数が整形できるオブジェクトはこれらに限られません。(有用な出力に整形できるかは別として)ほとんどのオブジェクトをpprint()関数で整形できます。
データを整形して標準出力へ出力する
pprint()関数は、引数に渡された(リストや辞書などの)オブジェクトを整形して標準出力へ出力します。出力の最後は改行されます。
pprint()関数の使い方さえマスターしてしまえば、pprintモジュールは、ほぼ理解できたも同然です。そのため、ここでpprint()関数使い方を詳しく調べていきます。
width引数
width引数には出力幅を指定します。デフォルトは80です。pprint()関数の出力は、このwidthの幅に収まるように整形されます。
pprint()関数は可能であれば1行に整形して出力します。1行がwidthの幅に収まらなければ複数行に整形して出力します。ただし、widthは努力目標なので、必ずこの幅に収まるとは限りません。データによって改行される場所が決まりますので、widthに収まるように改行できなければ、行はwidthの幅より長くなります。
widthの幅に収まるように1行で出力できるなら、次のようにpprint()関数は1行で出力します。
>>> pprint.pprint(animals, width=45) ['elephant', 'tiger', 'bear', 'hippopotamus']
出力はちょうど45文字でwidthの幅に収まるため、改行されずに1行で表示されます。次のように1行に収まらなければ複数行に整形されて出力します。
>>> pprint.pprint(animals, width=44) ['elephant', 'tiger', 'bear', 'hippopotamus']
次は辞書の例です。1行で出力しようとするとデフォルトの幅80に収まらないので、これも複数行に整形されます。なお、辞書はデフォルトでキーでソートされます。
>>> pprint.pprint(fruits) {'apple': {'color': 'red', 'price': 120}, 'banana': {'color': 'yellow', 'price': 180}, 'strawberry': {'color': 'red', 'price': 500}}
どこで改行されるかはデータ型に依存します。width=1を指定して、どこで改行されるか見てみましょう。
>>> pprint.pprint(animals, width=1) ['elephant', 'tiger', 'bear', 'hippopotamus'] >>> pprint.pprint(fruits, width=1) {'apple': {'color': 'red', 'price': 120}, 'banana': {'color': 'yellow', 'price': 180}, 'strawberry': {'color': 'red', 'price': 500}}
リストは変わりませんでしたが、ネストした辞書はいくつも場所で改行されました。この例から必ずしもwidthに収まるように整形されないこともわかるでしょう。
ネストした辞書のようにいくつかの場所で改行できる場合、widthの幅によって整形結果が変わります。次の例を見てください。
>>> pprint.pprint(fruits, width=60) {'apple': {'color': 'red', 'price': 120}, 'banana': {'color': 'yellow', 'price': 180}, 'strawberry': {'color': 'red', 'price': 500}}
外側の辞書のキーが1行となるように整形されました。
この結果から、辞書はまず1行で出力することを試みる。これがwidthの幅に収まらなければ(外側の)辞書の要素(キーと値)を1行で表示することを試みる。これもwidthの幅に収まらなく、値が複数の要素から成る場合は、その要素で改行する、と推測できます。正確にどのように改行されるかは構文解析を理解する必要がありそうです。いろいろなデータを試して慣れる方が楽でしょう。
indent引数
整形するときのインデントを指定します。デフォルトは1です。indent=4を指定するとこんな感じになります。
>>> pprint.pprint(animals, width=1, indent=4) [ 'elephant', 'tiger', 'bear', 'hippopotamus'] >>> pprint.pprint(fruits, width=1, indent=4) { 'apple': { 'color': 'red', 'price': 120}, 'banana': { 'color': 'yellow', 'price': 180}, 'strawberry': { 'color': 'red', 'price': 500}}
depth引数
どのレベルまで出力するかを指定します。デフォルトはNoneで、すべてのレベルを出力します。省略されたレベルは「...」で出力されます。どのような出力になるかは慣れが必要です。いろいろなdepthやwidthで試して見ましょう。
>>> pprint.pprint(fruits, depth=1) {'apple': {...}, 'banana': {...}, 'strawberry': {...}} >>> pprint.pprint(fruits, width=30, depth=1) {'apple': {...}, 'banana': {...}, 'strawberry': {...}} >>> pprint.pprint(fruits, width=20, depth=1) {'apple': {...}, 'banana': {...}, 'strawberry': {'color': 'red', 'price': 500}}
compact引数
compactのデフォルトはFalseです。Trueに設定すると、widthに収まる限り、多くの要素を1行で表示しようとします。
>>> pprint.pprint(animals, width=40, compact=True) ['elephant', 'tiger', 'bear', 'hippopotamus']
sort_dicts引数
sort_dictsのデフォルト値はTrueで、これは辞書を整形するときにキーでソートします。挿入された順番でそのまま整形したい場合、sort_dictsにFalseを指定します。
>>> pprint.pprint(fruits, sort_dicts=False) {'strawberry': {'price': 500, 'color': 'red'}, 'banana': {'price': 180, 'color': 'yellow'}, 'apple': {'price': 120, 'color': 'red'}}
stream引数
streamのデフォルト値はNoneで、この場合sys.stdoutが使われます。つまり出力先は標準ストリームになります。このキーワド引数に他のストリームオブジェクトを指定して出力先を変更することもできます。
データを文字列に整形する
データを整形してその結果を文字列として得るには、pprint.pformat()関数を使います。指定できる引数は次の通りで、pprint.pprint()関数とほとんど同じです(pformat()関数にはstream引数だけがない)。
- indent
- width
- depth
- compact
- sort_dicts
引数の使い方もデフォルト値もpprint()関数と全く同じなので、詳しくは「データを整形して標準出力へ出力する」を参照してください。
>>> formatted = pprint.pformat(fruits) >>> print(formatted) {'apple': {'color': 'red', 'price': 120}, 'banana': {'color': 'yellow', 'price': 180}, 'strawberry': {'color': 'red', 'price': 500}}
PrettyPrinterオブジェクトを使って整形する
これまでに説明したpprint.pprint()関数とpprint.pformat()関数は内部でPrettyPrinterオブジェクトを利用しています。pprint.pprint()とpprint.pformat()は利便性のために提供されている関数で、本来はPrettyPrinterオブジェクトを作成して、そのインスタンスメソッドを使うのが王道かもしれません。
PrettyPrinterオブジェクトはpprint.pprint()とpprint.pformat()と同じ名前のインスタンスメソッドを持っています。
PrettyPrinterコンストラクタに渡せる引数は次の通りです。引数の意味やデフォルト値はpprint.pprint()関数と同じですので、詳細は「データを整形して標準出力へ出力する」を参照ください。
- indent
- width
- depth
- stream
- compact
- sort_dicts
整形した結果を標準出力に表示する例を見てみましょう。
>>> pp = pprint.PrettyPrinter(width=1, indent=4) >>> pp.pprint(animals) [ 'elephant', 'tiger', 'bear', 'hippopotamus'] >>> pp.pprint(fruits) { 'apple': { 'color': 'red', 'price': 120}, 'banana': { 'color': 'yellow', 'price': 180}, 'strawberry': { 'color': 'red', 'price': 500}}
これは次の例と同じです。
>>> pprint.pprint(animals, width=1, indent=4) >>> pprint.pprint(fruits, width=1, indent=4)
整形した結果を文字列として得るにはpformat()メソッドを使います。
>>> formatted = pp.pformat(animals) >>> print(formatted) [ 'elephant', 'tiger', 'bear', 'hippopotamus']
ご想像通り、これは次の例と同じです。
>>> formatted = pprint.pformat(animals, width=1, indent=4) >>> print(formatted) [ 'elephant', 'tiger', 'bear', 'hippopotamus']
同じ整形ルールを何度も使いたい場合は、PrettyPrinterオブジェクトを使った方がわかりやすいでしょう。