シミュレーションや長時間かかる計算をJupyter Notebookで実行すると、大量の出力(ログ)によってNotebook自体の動作が重くなったり、次回開くのに時間がかかったりすることがあります。
本記事では、出力をNotebook上ではなく外部のテキストファイルに書き出すことで、Notebookを軽量に保つ方法を解説します。
1. 汎用的な方法(contextlibの使用)
Python標準ライブラリの contextlib を使用する方法です。 with ブロック内で実行されたコードの出力(標準出力・標準エラー出力)を、すべて指定したファイルへリダイレクトします。
以下のコードを実行すると、print 文やエラー内容が output.log に書き込まれます。
エラーの記録について
except ブロック内で print(e) とすればエラーメッセージのみを、traceback.print_exc() とすれば詳細なトレースバック(エラーの発生箇所などの情報)も含めてファイルに出力します。
- エラー時の動作について
except ブロックでエラーを捕捉しているため、通常はエラーが発生してもプログラムは停止せず、ログに記録した後に with ブロックを抜けて次の処理(print("notebookに表示") など)へ進みます。もし、エラーが起きた時点でNotebookの処理を強制的にストップさせたい場合は、raise のコメントアウトを外してください。こうすることで、Notebook上にもエラーが表示され、その場で処理が停止します。
import contextlib
import traceback
with open('output.log', 'w') as f:
with contextlib.redirect_stdout(f), contextlib.redirect_stderr(f):
print("Simulation Start")
try:
print("計算中")
# 実行したいコードを以下に記載
# opt = LBFGS(atoms)
# opt.run(fmax = 0.05)
except Exception as e:
# エラーメッセージだけを出力したい場合
# print(e)
# 詳細なエラー情報をファイルに書き込む場合
traceback.print_exc()
# エラーをNotebookにも通知し、処理を停止させたい場合
# raise
print("notebookに表示")
2. ASEを用いた計算を行う場合
構造最適化などのシミュレーションでASE(Atomic Simulation Environment)を使用している場合は、もっと簡単な方法があります。 多くのASEの計算モジュールには logfile という引数が用意されています。引数にファイル名を指定するだけで、自動的にそのファイルへログが出力されます。コード量が少なく記述がスッキリするため、ASEを使う際にはこちらの方法を推奨します。
# logfile引数に出力先を指定
opt = LBFGS(atoms, logfile="optimize.log")
opt.run(fmax = 0.05)