LoginSignup
0
0

More than 1 year has passed since last update.

【📖nbdev1入門】Dockerによる環境構築と作業手順

Last updated at Posted at 2022-06-27

2022年8月1日 追記)本記事はnbdev v1の手順であり、nbdev v2の手順とは異なります。

nbdev2版はこちら
https://qiita.com/lilacs/items/19c9c572a0740c5fc548

はじめに

nbdevはライブラリ作成の多くを自動化して、少人数での大規模プロジェクト開発をサポートしてくれる。しかし、その分環境構築が難しい。そこで、Dockerイメージを自作して、環境構築手順をまとめた。

また、nbdev独自の書き方が分からなかったので、書き方も自分なりにまとめた。

nbdevとは

参考:Welcome to nbdev | nbdev

  • Jupyter NotebookでPythonライブラリを開発し、すべてのコード、テスト、ドキュメントを1か所にまとめることができるライブラリです。
  • 文芸的プログラミング環境
    • コードスニペットとマクロを使用して、人間の言語でプログラムロジックを書き出すこと
    • コードと一緒にプログラムの背後にある考えを明示的に記述するので、設計上の決定が明白になり、高品質のプログラムを作成できる。

nbdevの機能

参考:nbdevへようこそ| nbdev

  • Jupyterノートブックからドキュメントを自動的に生成
    • Googleカスタム検索可能
    • バッククォートで囲んだキーワードは適切なドキュメントページに自動的にハイパーリンクされる
  • pypiおよびcondaパッケージの公開を自動化
  • ノートブックとソースコード間の双方向同期
    • IDEを使用してコードナビゲーションやクイック編集ができる
  • ノートブックで直接テストを作成
    • テストグループを定義できる
      • 長時間実行されるテストを常に実行する必要がないようにするため
  • 継続的インテグレーション(CI)でテストを自動的に実行
    • GitHub Actionsを使用
  • ドキュメントホスティング
    • GitHubページを使用してドキュメントを無料で簡単にホストできる

環境構築について

動作確認時の環境

セットアップするもの

  • GitHub プロジェクト
    • GitHub Pages も有効にする
  • Dockerイメージで対応するもの
    • Pythonランタイムとパッケージ(Jupyter/nbdev)
    • nbdevコマンド(nbdev_build_libなど)
    • jekyll (静的サイトジェネレータ、ドキュメント作成のため)
  • プロジェクトに設定するもの
    • git hooks
    • pip用インストールスクリプト(setup.py)

🐳nbdev用Dockerイメージ

公式イメージもあるが、エラーが出た(2022年6月27日時点)のと、自分用のDockerイメージが欲しかったので自作した。

環境構築手順

プロジェクト作成

GitHubにテンプレートから新しいプロジェクトを作成

以下のリンクから作成可能。
Create a New Repository from fastai/nbdev_template
image4.png

nbdevのテンプレート(fastai/nbdev_template - GitHub)を自分のリポジトリに複製して、プロジェクトを開始できる。

GitHub Pagesの有効化

Settings > Pages > Source > masterブランチを選択(masterをPagesのソースブランチにする場合)
image9.png

リポジトリをローカルに複製

bash
git clone (作成したプロジェクトのURL)

settings.iniを編集

ライブラリをパッケージ化するのに必要な情報を設定する。

主な設定内容

settings.ini
# lib_name = your_project_name
# repo_name = name of github repo
# user = your_github_username
# description = A description of your project
# keywords = some keywords
# author = Your Name
# author_email = email@example.com
# copyright = Your Name or Company Name
# branch = The default branch of your GitHub repo (usually either master or main)

fastai/fastaiリポジトリのように、Jupyter Notebookをnbsフォルダにまとめる場合は、以下の項目を設定すること

settings.ini
nbs_path = nbs

以下の項目も入力しておくこと。
一見なくても大丈夫そうだが、setup.pyの実行時にAssertionエラーになってしまうため。
参考: nbdev_template/setup.py のcfg_keysとexpectedより。

settings.ini
version
description
keywords
author
author_email
lib_name
user
branch
license
status
min_python
audience
language

実行環境の構築(Dockerで)

参考 https://github.com/lilacs2039/docker_fastai-nbdev

🐳Dockerイメージ取得・実行

プロジェクトルートで以下のコマンドを実行する。
(Windowsの場合は、wsl環境で実行のこと)

bash
# 本リポジトリの`docker-compose.yml`を取得
wget https://raw.githubusercontent.com/lilacs2039/docker_fastai-nbdev/main/docker-compose.yml
# 環境立ち上げ
docker compose up

※「pytorch/pytorch:1.11.0-cuda11.3-cudnn8-runtime」イメージを使うため、5GB以上のイメージサイズになるので注意。

ローカルサーバへアクセス

プロジェクトにGitフックのインストール

JupyterLab(http://localhost:8888)のTerminalから、以下のコマンドを実行する

bash
nbdev_install_git_hooks

ファイル.git/hooks/post-mergeが追加される。
※実行エラーになっても、.git/hooks/post-mergeファイルはちゃんと作成されているかも。

開発手順

Notebook編集・ドキュメントのプレビュー

1.ドキュメントに編集内容を反映

bash
nbdev_build_docs

2.ドキュメントのプレビューをリロード

プレビュー:http://localhost:4000/(lib_name)//
※プレビューがうまくいかないときは、必要に応じてsudo make docs_serveを実行のこと。

  1. 古い内容がドキュメントに表示される場合、jekyllサーバを再起動すると直ることがある。
  2. Ctrl+Cでサーバをいったん終了してから、本コマンドで再起動する。

コミット

1.コミット準備

bash
# モジュールのエクスポート(Notebookから実行)
nbdev_build_lib

# ドキュメントの出力
nbdev_build_docs

# テストの実施
nbdev_test_nbs

# Notebookをきれいに
nbdev_clean_nbs
  • 備考
    • nbdev_test_nbs
      • すべてのノートブックのテストを並行実行できる
    • nbdev_clean_nbs
      • 実行番号などは除去される。アウトプットは残る。
      • Notebookの競合を避けるため。

2.コミットを実行する

リリース

  1. GitHubへプッシュ
    1. GitHub Pagesにドキュメントがホストされる
    2. CIで自動実行されるもの
      1. テスト
      2. Pythonモジュール
      3. ドキュメント
    3. CIの注意点:以下の項目が設定されていないと、setup.pyの実行時にAssertionエラーが出てしまう。settings.iniに記述が必要。
      4. version description keywords author author_email lib_name user branch license status min_python audience language
  2. PyPIへアップロード
    4. ここまでの作業で、プロジェクト用に完全にpypiに準拠したインストーラーをすでに作成済み。
    5. PyPIアップロードの準備
    5. PyPIにアカウント登録し(まだの場合)、ログイン情報を含むファイルを作成する。
    6. 「~/.pypirc」に以下の内容を記述する。
    1. [pypi]
    2. username = your_pypi_username
    3. password = your_pypi_password
    6. PyPIへのアップロード
    7. プロジェクトルートで以下のコマンドを入力
    4. make pypi
    5. (ホントは「make release」コマンドによるPyPI/Conda両方へのアップロードが推奨)

📖nbdevの記述方法

概要

🪐JupyterNotebookだけを編集しながら、アウトプットの「🐞テスト・🐍ライブラリ・📃ドキュメント」を意識して記述すること。

  • 🐞テスト
    • 書き方:Notebookにassert文を記述
    • Notebookの正常な実行をもってテストとする。
  • 🐍ライブラリ(*.py)
    • 書き方
      • モジュール分割:Notebookの先頭に# default_exp (モジュール名)を記述
      • 関数・クラス定義:#exportをつけたセルが出力される。
  • 📃ドキュメント
    • 書き方:Notebookのほぼ全ての内容がドキュメントに出力される。(#hideで抑制)
    • 見出しを付けて適切な論理構造でNotebookを記述すれば、そのまま読みやすいドキュメントになる。

ライブラリ・ドキュメントへの出力制御

セルのキーワードによって、出力するか・しないかを切り替えることができる。

🐍ライブラリ 📃ドキュメント
(キーワードなし) ❌しない ✅する
#export ✅する ✅する(クラス・関数定義のみ?)
#hide ❌しない ❌しない
#export #hide ✅する ❌しない

記述例

nbdevで、Notebookに記述した内容がどのようにドキュメントに変換されるか比較した。

🪐Notebook 📃ドキュメント
(参考URL) https://github.com/fastai/deck_of_cards/blob/master/00_card.ipynb https://fastai.github.io/deck_of_cards/card.html
モジュール名の指示 image.png
モジュール名:deck_of_cards.card
出力ファイル名:deck_of_cards/card.py ※
-
見出し1 image.png image.png
目次 (自動生成) - image.png
import****文 (出力しない) image.png -
クラス定義 **(コード) ** image.png image.png
説明 (マークダウン) image.png image.png
実行例 (コード) image.png image.png
assert****文によるテスト (コード) image.png image.png
(中略**)** (中略) (中略)
show_docs (ドキュメントに関数定義を表示) image.png image.png

※本例のライブラリ名はdeck_of_cards

入力・出力ファイルの対応

以下のような対応で、入力ファイル(Jupyter Notebook)に対して出力ファイル(ライブラリ・ドキュメント・README.md)が生成される。

🪐Notebook 🐍ライブラリ 📃ドキュメント その他
index.ipynb - docs/index.html(ドキュメントのトップページ) README.md
*.ipynb *.py docs/*.html(ドキュメント) -

便利機能

nbdev_clean_nbs

重要でないメタデータを除去して、Notebookをコンフリクトしにくくする。
Outputなどは変わらない。

全部 Notebook****指定
nbdev_clean_nbs nbdev_clean_nbs --fname (Notebook名)
Before After
image.png image.png
...
   "execution_count": 5,
...
...
   "execution_count": null,
...

所感

  • nbdevは、少人数で大規模プロジェクトを開発できることを目標にしている。
    • 反面、小さいパッケージを作りたい時は、機能が多すぎで余分な作業が多いかもしれない。(PyPIへの登録やGitHub Pagesでのドキュメントなど)
  • 以下の整合性を同時に取りながらノートブックを記述するのが難しく慣れが必要。
    • Notebook:ソースコード(*.ipynb)の可読性は問題ないか
    • ライブラリ:モジュール(*.py)に必要なコードをexportしているか
    • ドキュメント:順番に読んだとき意味の通る内容になるか
    • テスト:コード(*.ipynb)の実行は成功するか
  • これをするには出力制御構文(#export, #hide, show_doc(...))の挙動を正しく理解する必要がある
  • 成果物を同時に作るのが難しい分、成果物の良くない点はソースコード(*.ipynb)の作成中に気づくので、すぐ修正できる。結果、PDCAが速く回り、生産性が向上する。
0
0
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
0
0