技術研究所(技研)のまつけんです。

 

技研では現在、3台のゲーミングデスクトップPCにLinux (Ubuntu)とJupyterをインストールして、共有で計算サーバとして使っています。私も、画像処理や機械学習のタスクをJupyterで行っています。また、開発中のソースコードなどはSubversionで管理しています。今回は、私が実践しているJupyter上でのソースコードのバージョン管理の手法について紹介したいと思います。

具体的には、各notebook (.ipynbファイル) の冒頭に専用のセルを用意し、そこに以下のスクリプトを入れておきます (この例ではabc.ipynbというnotebookを想定):

F = 'abc' ; FB = F + '.ipynb' ; FP = F + '.py'
### commit resp.
#!date ; sed -e 's#[ t]+(\n",)$#1#g' -i $FB ; svn commit $FB -m "$F (ipynb)"
#!date ; jupyter nbconvert --to script $FB ; sed -e 's/# In[[0-9]+]:/# In[ ]:/' -e 's#[ t]+$##' -i $FP ; svn commit $FP -m "$F (py)"
### commit both
#!date ; sed -e 's#[ t]+(\n",)$#1#g' -i $FB ; jupyter nbconvert --to script $FB ; sed -e 's/# In[[0-9]+]:/# In[ ]:/' -e 's#[ t]+$##' -i $FP ; svn commit $FP $FB -m "$F (both)"
### diff resp.
#!date ; sed -e 's#[ t]+(\n",)$#1#g' -i $FB ; svn diff $FB
#!date ; jupyter nbconvert --to script $FB ; sed -e 's/# In[[0-9]+]:/# In[ ]:/' -e 's#[ t]+$##' -i $FP ; svn diff $FP
### diff both
#!date ; sed -e 's#[ t]+(\n",)$#1#g' -i $FB ; jupyter nbconvert --to script $FB ; sed -e 's/# In[[0-9]+]:/# In[ ]:/' -e 's#[ t]+$##' -i $FP ; svn diff $FP $FB
### revert
#!date ; svn revert $FP $FB
### commit all
#!date ; F='*' ; sed -e 's#[ t]+(\n",)$#1#g' -i $FB ; jupyter nbconvert --to script $FB ; sed -e 's/# In[[0-9]+]:/# In[ ]:/' -e 's#[ t]+$##' -i $FP ; svn commit $FP $FB -m 'all .ipynb, .py'
### diff all
#!date ; F='*' ; sed -e 's#[ t]+(\n",)$#1#g' -i $FB ; jupyter nbconvert --to script $FB ; sed -e 's/# In[[0-9]+]:/# In[ ]:/' -e 's#[ t]+$##' -i $FP ; svn diff *.py *.ipynb
del F, FB, FP
print('================ DONE ================')

7つのブロックに分かれたシェルスクリプトが書いてありますが、上から順に

  1. commit respectively: .ipynbと.pyを個別にコミット
  2. commit both: .ipynbと.pyを両方ともコミット
  3. diff respectively: .ipynbと.pyの差分を個別に表示
  4. diff: .ipynbと.pyの差分を両方とも表示
  5. revert: 元に戻す
  6. commit all: ディレクトリ内の全ての.ipynbと.pyをコミット
  7. diff.all: ディレクトリ内の全ての.ipynbと.pyの差分を表示

です。使う際は、コメントアウトを解除 (行頭の「#」を一時的に除去) して、ctrl-enter (Ctrlキーを押しながらEnterキーを押す) で実行します。

バージョン管理するのは、.ipynbファイルだけでも良いのですが、svn diffなどで差分を見る際に、ipynbファイルの差分を見るとなると少し見辛いので、一緒に.pyファイルもコミットすることにしています。jupyter nbconvert –to scriptで.ipynbを.pyに変換できるので、それを組み込んでいます。また、行末のスペースをsedコマンドで除去しています。

なお、svnサーバの容量節約のためと、diffの見やすさを考えると、.ipynbファイルをコミットする前に”clear output”を実行するのがオススメですが、

cp -af $FB $FB.bak ; jupyter nbconvert --clear-output --inplace $FB

mv -f $FB.bak $FB

をcommitとdiffの前後に入れてしまうのも良さそうです (または、「–ClearOutputPreprocessor.enabled=True」) [1]。

最初に「F = ‘abc’」という形でnotebookの自身のファイル名を指定しています。Notebook自身のファイル名を取得する方法[2]はありますが、新たにnotebookを作成した際に手動で指定してしまえば、その後は変更することも無いので、そのようにしています。

Subversion以外にも (Gitなどでも) 利用できるかと思いますので、よろしければ試してみてください。