3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Python】デバッグ時に便利なIcecreamを真似てprintをオーバーライドしてみた。

Last updated at Posted at 2021-01-27

はじめに

こちらの記事
デバッグ時はprintではなく、Icecreamを使うと便利
を見て自分で似たような機能を作ってみたくなったので書いてみました。

printをオーバーライドすることで既存のプログラムを書き換えることなく、一番上の行にインポート文ないしは定義文を書くだけでIcecreamを使った際のような表示が可能になります(つまり逆にコメントアウトをすればすぐに元に戻せるということです)。

つくったもの

printer.py
def print(*args, sep=' ', end='\n', file='', flush=False):
    import builtins, inspect, re, sys
    if not file: file = sys.stdout
    fr = inspect.currentframe().f_back
    arg_names = re.split(
        '\s*,\s*',
        re.findall(
            'print\(((?:.|\s)+?)\)', ''.join(
                inspect.getframeinfo(fr, min(1000,
                                             fr.f_lineno)).code_context))[-1])
    builtins.print(*[
        f'{k}: {v}' if
        not re.match('[\"\'\(\[\{0-9]', k.lstrip()) else str(v)
        for k, v in zip(arg_names, args)
    ],
                   sep=sep,
                   end=end,
                   file=file,
                   flush=flush)

使用例

なるべくprintと同じような感覚で使えるように、sependfileなどといった引数を取ることができます。

例えば以下のようなプログラムがあったとします。

a = 1
b = "abcABC"
c = [1, 2, 3]
d = {"A": "a", "B": "b", "C": "c"}
e = {1, 1, 2, 3, 4, 4, 4, 5}

print(a, b, c, d, e)

もちろん出力は

out
1 abcABC [1, 2, 3] {'A': 'a', 'B': 'b', 'C': 'c'} {1, 2, 3, 4, 5}

となりますね。
ここに先程の関数をインポートしてみます。すると、

from printer import print

a = 1
b = "abcABC"
c = [1, 2, 3]
d = {"A": "a", "B": "b", "C": "c"}
e = {1, 1, 2, 3, 4, 4, 4, 5}

print(a, b, c, d, e)
out
a: 1 b: abcABC c: [1, 2, 3] d: {'A': 'a', 'B': 'b', 'C': 'c'} e: {1, 2, 3, 4, 5}

プログラムを書き換えることなく変数名を表示することができます。
先程説明したとおり、sepなどを指定することで

print(a, b, c, d, e, sep='\n')
out
a: 1
b: abcABC
c: [1, 2, 3]
d: {'A': 'a', 'B': 'b', 'C': 'c'}
e: {1, 2, 3, 4, 5}

より見やすく出力したり、

with open('log.txt', 'w') as f:
    print(a, b, c, d, e, file=f)

外部ファイルに出力するなどといったことも、通常のprint同様可能です。

仕組み

標準ライブラリinspectを使うことで呼び出し元のコードを取得し、そこから正規表現で変数名を抽出、整形して出力しています。
その性質上、

print(a, b, c);print(d, e)

のような書き方をすると上手く変数名を抽出できないのでその点は注意してください(これはIcecreamも同じ)。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?