諸事情ありまして、jupyter notebookのセルの出力をクリアする方法を知りたくなったので調べました。
通常、jupyterではテキストを複数回にわたってprintしたり、matplotlibの図をいくつも出力するコードを1つのセルに書くと、出力したテキストなり図なりがダーっと続けて出てきます。
ちょっとこれを逐一クリアして新しいものだけ残すようにしたかったのです。
(こんなことする必要があることは滅多にないのですが。)
実は、クリアしたい対象がprintした1行以内のテキストの場合、それを実装する方法は過去に紹介したことがあります。それはprintメソッドのend引数を使ってprint後に改行コードを出力しないようにし、キャリッジリターン(“\r”)で出力位置を行頭に戻して空白で上書きしてしまうというものです。
これ使ってプログレスバーを作った記事が過去にありますね。
参考: printでお手軽プログレスバー
例えば、jupyterで次のコードを動かすと0~49まで数字がカウントアップします。
\r でカーソルを先頭にもどして、空白で埋めて、最後に次のprintのためにもう一回カーソルを先頭に戻しています。 end=”” はprint後に改行させない設定です。
sleep() は入れておかないと一瞬すぎて何も見えないのでウェイトとして入れています。
import time
for i in range(50):
print("\r \r", end="")
print(i, end="")
time.sleep(0.5)
ただ、さっきも書きましたがこの方法だと1行のテキストしか消せません。
複数行の出力だったらどうやって消すのかなと思って調べた結果見つかったのが、IPython モジュールにあった、 clear_output というメソッドです。
正確には、IPython.display.clear_output として実装されています。
ドキュメントはこちらです。
参考: Module: display — IPython 7.30.1 documentation
Clear the output of the current cell receiving output. とある通り、これが実行されるとそのステップが含まれたセルの出力だけを消してくれます。他のセルの出力は残してくれるので安心ですね。
wait (デフォルトはFalse)という便利な引数も持っています。これは、Falseにしておくと即座に出力を消すのに対して、Trueを渡すと、次の出力がくるのを待って消してくれます。連続して何かを出力するようなコードの場合、Trueにしておくと出力をスムーズに入れ替えるような動きになるのです。 Falseだと一瞬何も出力がない状態になるので次のセルとの間が詰まって 以降のセルがガクガク動きます。
以下のようにして、1秒ごとに現在時刻を表示する時計のような出力も出せます。
from IPython.display import clear_output
from datetime import datetime
import time
for i in range(10):
print("現在時刻\n", datetime.now())
clear_output(True)
time.sleep(1)
"""
現在時刻
2021-12-14 23:58:34.942141
上のような出力が1秒ごとに更新されて書き換えられる
"""
clear_outputはテキストだけではなく、図もクリアしてくれます。これを応用すると、パラパラ漫画のようにして手軽にアニメーションを作ることができます。
徐々にデータが増えて延びる折れ線グラフを描いてみたのが次のコードです。
import matplotlib.pyplot as plt
import numpy as np
# プロットする点を格納する配列
X = []
Y = []
for i in range(100):
# 新しい点を追加する
X.append(i)
Y.append(np.random.randn()) # y座標には乱数入れる
clear_output(True) # それまでの出力をクリアする
# グラフ作図
fig = plt.figure(facecolor="w") # 出力をクリアしたら改めてfigreオブジェクトが必要らしい
ax = fig.add_subplot(111)
ax.plot(X, Y)
# グラフ表示
plt.show()
time.sleep(0.1)
このコードで jupyter 上にはアニメーションが表示できます。
実質的には clear_output(True) を差し込んでるだけなので、かなり手軽ですね。
ただ、これには一つ欠点もあって、jpyter上で簡易的に図を書いたり消したりしてアニメーションっぽく見せているだけなのでこのまま動画として保存することはできません。
(そのためこの記事にも結果の画像を貼っていません)
もし、gif形式などで保存したい場合は、少々面倒になるのですが、 ArtistAnimation などを使いましょう。過去の記事で取り上げています。
参考: matplotlibでgif動画生成