たくさんのnotebookの内容をコマンドラインから再実行して更新したい
はじめに
たとえばグラフを描画するnotebookをたくさん開いている状態。 ちょっとだけimportしたライブラリに変更があったので実行結果が変わりそうになってしまった。 このようなときに、すべてのipynbファイルを開いてrunallした後にsaveというようなことを手動で行いたくない。
はじめはheadless jupyterのようなものを作ろうとしたけれど。nbconvertで大丈夫だったという話。
nbconvert --execute
jupyterにはnbconvertというコマンドもついてくる。
これは、ipynbファイルを別のフォーマット(例えば、pdfだったりhtmlだったりmarkdownだったり)に変換するためのコマンドという認識だったのだけれど。
なんと--execute
というオプションがついている。
これを使うことで再実行が可能になる。こういう感じ。
$ jupyter nbconvert --to notebook --execute Untitled.ipynb
すると、 Untitled.nbconvert.ipynb
というファイルに再実行した結果が保存される。
--inplace
を使えば上書き保存できる
--inplace
を使えば上書き保存できる。こういう感じ。
$ jupyter nbconvert --to notebook --execute Untitled.ipynb
これは、Untitled.ipynbが更新される。
timeoutも伸ばしておいた方が良いかもしれない。
defaultでは30秒のtimeoutが設定されている。30秒以上掛かるような処理だった場合に中断されてしまうのは悲しい。そんなわけでtimeoutを伸ばしておくと良い。
$ jupyter nbconvert --ExecutePreprocessor.timeout=600 --to notebook --execute Untitled.ipynb
おまけ: 手で書いたipynbをレンダリングさせるということもできなくはない
こういう雑なmatplotlibで図を描くコードがあるとする。
import matplotlib.pyplot as plt plt.style.use("ggplot") xs = list(range(10)) ys = [x * x for x in xs] plt.plot(xs, ys, "g")
これを以下のようにipynbに手動で変換する(metadataなど埋めたほうが良い部分はあったりする)
{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "source": [ "%matplotlib inline\n", "import matplotlib.pyplot as plt\n", "plt.style.use('ggplot')\n", "\n", "xs = list(range(10))\n", "ys = [x * x for x in xs]\n", "plt.plot(xs, ys, 'g')" ] } ], "metadata": {}, "nbformat": 4, "nbformat_minor": 2 }
.ipynbはJSONファイルなので手書き出来ないことはない。例えばgraph.ipynbなどの名前で保存しておく。
その後この保存したファイルに対してnbconvert --execute
を実行してグラフも含んだipynbを手に入れる事ができる。
(警告が出ているので本当はもう少し真面目にjson書いた方が良いかもしれない)
$ jupyter nbconvert --ExecutePreprocessor.timeout=600 --execute --to notebook 01graph.ipynb [NbConvertApp] Converting notebook 01graph.ipynb to notebook [NbConvertApp] ERROR | Notebook JSON is invalid: 'outputs' is a required property Failed validating 'required' in code_cell: On instance['cells'][0]: {'cell_type': 'code', 'execution_count': 1, 'metadata': {}, 'source': 'import matplotlib.pyplot as plt\n' "plt.style.use('ggplot')\n" '\n' 'xs = li...'} [NbConvertApp] Executing notebook with kernel: python [NbConvertApp] Writing 570 bytes to 01graph.nbconvert.ipynb
たくさん一気に同様の形式で別のファイルにグラフを描きたいときなどには便利かもしれない。
すると以下の様なグラフを生成した結果を含んだipynbが作れる。
(例が二次関数のグラフなのは寂しいのでもうちょっと良い感じの絵を表示するようなものにしたい気持ちもあったりする)
gistはこちら
追記: ipynbの作成にはnbformatを使うと便利
ipynbの作成にはJSONを手書きするよりnbformatを使うと便利。
例えば以下の様な形で使う。
import textwrap from nbformat.v4 import new_code_cell, new_notebook, writes_json notebook = new_notebook() sources = [ """ import random random.random() """, """ import random random.random() """, ] for i, source in enumerate(sources, 1): notebook["cells"].append(new_code_cell(textwrap.dedent(source), execution_count=i)) print(writes_json(notebook))
これを実行すると以下の様なipynbが生成される。便利。
{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "\n", "import random\n", "random.random()\n" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "\n", "import random\n", "random.random()\n" ] } ], "metadata": {}, "nbformat": 4, "nbformat_minor": 2 }