はじめに
下記記事にてIceCreamというライブラリを知り、最近使用しています。
デバッグ時はprintではなく、Icecreamを使うと便利
https://qiita.com/purun/items/c7aca300b970344214cf
IceCreamの機能についての日本語記事が見当たらないので、簡単にまとめました。
内容については基本的には公式READMEを参考にしていますが、
手元での実行結果とドキュメントで挙動が異なるものは実行結果を正として記載しています。
動作確認versionは2.0.0です。
インストール
$ pip install icecream
基本機能
引数ありで実行
ic()
に引数を渡すと、渡した引数とその値を出力してくれます。
from icecream import ic
def foo(i):
return i + 333
ic(foo(123))
ic| foo(123): 456
下記の場合も同様。
d = {'key': {1: 'one'}}
ic(d['key'][1])
class klass():
attr = 'yep'
ic(klass.attr)
ic| d['key'][1]: 'one'
ic| klass.attr: 'yep'
値を複数渡すこともできます
ic(foo(123), d['key'][1], klass.attr)
ic| foo(123): 456, d['key'][1]: 'one', klass.attr: 'yep'
なお、Python3.8以降であれば、f文字列で同様の出力ができるようです。
print(f"{foo(123)=}")
foo(123)=456
ic()
を使用した場合と比べ記述が煩雑になりますが、わざわざIceCreamをインストールせずともこちらで十分な場合もあるでしょう。
引数なしで実行
ic()
を引数なしで実行した場合は、実行箇所のファイル名、行数、関数名、実行時刻(UTC)を出力してくれます。
これを利用して、処理実行の有無や処理順のチェックを行うことができます。
from icecream import ic
def foo():
ic()
first()
if expression:
ic()
second()
else:
ic()
third()
出力:
ic| main.py:4 in foo() at 12:49:18.489
ic| main.py:11 in foo() at 12:49:18.491
これは、下記のようにprint()
に自前の引数を渡してデバッグするよりスマートです。
def foo():
print(0)
first()
if expression:
print(1)
second()
else:
print(2)
third()
なお、ic()
に引数を渡す場合でも、設定によってこれらのコンテキスト情報を出力することができます。(後述)
その他
戻り値
ic()
は受け取った引数をそのまま返すため、既存のコードに簡単に挿入できます。
from icecream import ic
a = 6
def half(i):
return i / 2
b = half(ic(a))
ic| a: 6
文字列を返す
コンソールへの出力を行うかわりに、ic.format()
を使用することで文字列を返します。
s = 'sup'
out = ic.format(s)
print(out)
s: 'sup'
出力の無効化/有効化
ic.disable()
, ic.enable()
を呼ぶことで出力の無効化/有効化を行います。
ic(1)
ic.disable()
ic(2)
ic.enable()
ic(3)
出力
ic| 1: 1
ic| 3: 3
ic.disable()
することで、出力が止められます。
なお、disableで止まるのは標準エラーへの出力のみで、ic()
,ic.format()
からの戻り値はenable時と同様に返却されます。
カスタム出力設定
ic.configureOutput()
メソッドを使用して、出力値のカスタマイズができます。
prefix
出力のprefix。デフォルトは"ic|"。
ic.configureOutput(prefix='hello -> ')
ic('world')
hello -> 'world'
関数を渡すこともできます。
def unixTimestamp():
return '%i |> ' % int(time.time())
ic.configureOutput(prefix=unixTimestamp)
ic('world')
1519185860 |> 'world': 'world'
outputFunction
文字列の出力処理にカスタム関数を渡すことができます。
デフォルトの関数 では、pygmentsによるシンタックスハイライトを行ってstderrへ出力しています。
以下の例では、logging.warning()を行うカスタム関数を渡しています。
def warn(s):
logging.warning(s)
ic.configureOutput(outputFunction=warn)
ic('eep')
WARNING:root:ic| 'eep': 'eep'
上記の例を見るとわかりますが、ic| 'eep': 'eep'
という生成済み文字列を受け取り、
その出力を行う関数を定義できます。
argToStringFunction
値を文字列に変換する関数を定義できます。
デフォルトでは、値はpprint.pformat()で整形して出力されます。
特定の型のオブジェクトに対して出力形式を定義したい場合なんかに便利そうです。
import pprint
from icecream import ic
class Person:
def __init__(self, name):
self.name = name
p=Person(name="taro")
ic(p)
def toString(obj):
if isinstance(obj, Person):
return obj.name
return pprint.pformat(obj)
ic.configureOutput(argToStringFunction=toString)
ic(p)
出力:
ic| p: <__main__.Person object at 0x10795fd60>
ic| p: taro
includeContext
引数を渡して実行する時の、ファイル名・行数・親関数名を出力するオプションです。
includeContextをTrueにすることで引数を渡した際もこのコンテクスト情報を出力できます。
引数なしでの実行には影響しません。
from icecream import ic
ic(0)
ic.configureOutput(includeContext=True)
ic(1)
ic.configureOutput(includeContext=False)
ic(2)
ic| arg: 0
ic| main.py:4 in foo()- arg: 1
ic| arg: 2
引数がない時の出力と異なり、時刻情報は出力されません。
from icecream import ic
ic.configureOutput(includeContext=True)
ic()
ic(0)
ic| main.py:5 in <module> at 12:56:38.755
ic| main.py:6 in <module>- 0
※2.0.0時点で設定できないこと
- 文字列フォーマットのカスタマイズ
-
<prefix> <context> - <arg>: <val>
という出力形式は変更できない
-
- 引数なし実行時の時刻出力
- 出力時刻のタイムゾーン変更
ちなみに
Node.js, PHP, Go 等の他言語向けにも同様のライブラリがあるっぽい。
→ https://github.com/gruns/icecream#icecream-in-other-languages