🐍

Poetryとmkdocsとsphinxを使ってPythonのプロジェクトを作る

2023/04/02に公開

お仕事でpythonを使うことがあって、その開発環境をどうやって整備しようかと思っていたところでした。

よくある構成のpyenv+poetryのpython開発環境を作るとともに、ドキュメントもちゃんとやりたいなということで、ユーザー向けのAPIドキュメントに加えて、Pythonコードの設計とかを記述できるように開発者向けドキュメントとしてmkdocsを併用したpythonプロジェクトの環境を作ってみました。

この記事では作るまでの流れを自分のための備忘録的な感じで残しておこうと思います。

今回試した環境

  • Ubuntu 22.04.2 LTS (MacBook Air M1のLima 0.15.0上で動かしてます)
  • docker: Docker version 23.0.1, build a5ee5b1
  • docker compose: Docker Compose version v2.16.0
  • vs code: 1.76.2

環境を作るまでの流れ

環境を作るまでの流れは下記の感じで作成します。

  1. pyenvpoetryのpythonプロジェクトの初期環境を作る
  2. 開発用のライブラリを入れる
  3. Sphinxを使ってユーザー向けAPIドキュメントが作れるようにする
  4. mkdocsを使って開発者向けドキュメントが作れるようにする

これらをまとめてdev containerにまとめてツヨツヨ環境を作りたいのですが、そちらはまた後日です。。。

各種必要なものをインストール

インストール方法については色んなサイトで紹介されていると思うので、他のところを参照してもらえばと思います。

Pythonプロジェクトのテンプレート作成

まずはpyenvを使って、systemのpythonからバージョンをstableなpythonが使えるようにしておきます。(別にやらなくてもいいかもですが)

pyenv install 3.11.2;
pyenv global 3.11.2;

次にpoetryの初期設定として、poetryで作る仮想環境はプロジェクト直下で生成されるようにしておきます。

poetry config virtualenvs.in-project true

poetryを使ってpythonのプロジェクトを作っていきます。

poetry new python-project-with-mkdocs;
cd python-project-with-mkdocs;

下記ディレクトリ構成になります。

.
├── README.md
├── pyproject.toml
├── python_project_with_mkdocs
│   └── __init__.py
└── tests
    └── __init__.py

gitでプロジェクト管理できるようにプロジェクトフォルダでgit initでもしておいてください。

まずはpyenvを使ってこのプロジェクトで利用する仮想環境のバージョンを固定して

pyenv local 3.11.2;

poetryで仮想環境を作って、activateさせてしまいます。これ以降の環境はすべてプロジェクトディレクトリの.venvがactivateされた状態でpoetryを使って作業していきます。

$ poetry shell
Creating virtualenv python-project-with-mkdocs in YOURPROJECT/python-project-with-mkdocs/.venv
Spawning shell within YOURPROJECT/python-project-with-mkdocs/.venv
$ emulate bash -c '. YOURPROJECT/python-project-with-mkdocs/.venv/bin/activate'
(python-project-with-mkdocs-py3.10) $

.venvはいらんので.gitignoreでgitの管理外にしておいたほうが良さそうですね。

ここまででpythonプロジェクトでの開発準備が整いました。

必要に応じて、flake8やblackなどの開発用ライブラリをインストールします。
今回は例として下記のもの開発用ライブラリとしてインストールします。

poetry add --group dev flake8 black pre-commit

ここまでのディレクトリ構成は下記です。

.
├── README.md
├── poetry.lock
├── pyproject.toml
├── python_project_with_mkdocs
│   └── __init__.py
├── scripts
└── tests
    └── __init__.py

Sphinxの導入

pythonで開発するためのプロジェクトのテンプレートができたので、続いてはSphinxを道入して開発者向けAPIドキュメントを作れるようにしておきます。

poetryで入れてしまいます。ついでにテーマもかっこよくしたいので、Furoを入れてみます。

poetry add --group dev sphinx furo

下記実行して、sphinxのドキュメントを初期化します。今回は適当にすべてデフォルトでenterですが、project nameとauthorを適当に入れて作ります。

$ sphinx-quickstart api-docs
.
.
The project name will occur in several places in the built documentation.
> Project name: python_project_with_mkdocs
> Author name(s): okojomoeko

下記でpythonのdocstringsから.rstのテンプレートを作ります。

sphinx-apidoc -f -o api-docs python_project_with_mkdocs

conf.pyにパス設定とextensions、テーマにfuroを使うことなど設定します。

conf.py
import os
import sys
sys.path.insert(0, os.path.abspath('../'))
.
.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon']
html_theme = 'furo'

これでSphinxを使ってAPIドキュメントをビルドできるようにりました。下記適当なサンプル関数を用意して、

sample_calc.py
def add(a: float, b: float) -> float:
    """数値の足し算を行う

    Args:
        a (float): float型の数値
        b (float): float型の数値

    Returns:
        float: 数値a, bの合計結果
    """
    return float(a + b)

def print_add_1p10() -> None:
    """1と10を足した結果を表示する

    Args:
        None

    Returns:
        None
    """
    print(add(1,10))

APIドキュメントをビルドしてみます。

sphinx-build api-docs api-docs/_build

_buildの中身のindex.htmlを見てみると、下記みたいなライブラリのドキュメントが生成されていると思います。

APIドキュメント

邪魔なので、build結果(api-docs/_build)はgit管理から外しておいてもいいと思います。

ここまでのディレクトリ構成は下記になります。

.
├── Dockerfile
├── README.md
├── api-docs (一部省略)
│   ├── Makefile
│   ├── _build
│   ├── conf.py
│   └── python_project_with_mkdocs.rst
├── poetry.lock
├── pyproject.toml
├── python_project_with_mkdocs
│   ├── __init__.py
│   └── sample_calc.py
├── scripts
└── tests
    └── __init__.py

mkdocsの用意

開発用ドキュメントの環境としてmkdocsを使用する例が多々ありますが、各種拡張によってpythonのdocstringsを参照できるようにしたり、plantumlで図を扱ったりできるようになります。

poetryで開発用のライブラリとして追加していってもいいのですが、Sphinxではそのやり方を試したのでお手製Dockerイメージで開発用ドキュメントをビルドしたり見られたりする環境を整えてみます。

plantumlの記法を描画するserverが必要になってきますが、お仕事用の閉じた環境で扱うことを想定しているので、公開されているAPIなどを経由せずにplantumlのcontainerを使っています。

mkdocsのpluginを多々インストールしていますが、重要なのはmkdocstringsplantuml-markdownなのでそれ以外のpluginは個人の自由です。

Dockerfile
FROM python:3-buster

WORKDIR /app

RUN pip install -U \
        pip \
        mkdocs \
        mkdocs-autorefs \
        mkdocs-material \
        mkdocs-markmap \
        mkdocs-material-extensions \
        mkdocstrings \
        mkdocstrings-python \
        plantuml-markdown \
        fontawesome-markdown \
        mdx_unimoji \
        python-markdown-math \
        pymdown-extensions
docker-compose.yml
version: "3.7"

services:
  plantuml:
    image: plantuml/plantuml-server
    ports:
      - 8080:8080

  mkdocs:
    build:
      context: ./
      dockerfile: ./Dockerfile
    volumes:
      - ./:/app
    ports:
      - 8000:8000
    tty: true
    depends_on:
      - "plantuml"
    command: >
      bash -c "mkdocs serve -a 0.0.0.0:8000"

mkdocsの設定

mkdocs.ymlを用いて設定を行っていきますが、ここでは目的に対して重要な部分の設定のみ記載します。

pluginsでmkdocstringsを有効化し、markdown_extensionsでplantumlのcontainerをserverとして設定します。

mkdocs.yml
site_name: My Docs

theme:
  feature:
  .
  .

plugins:
  - mkdocstrings

markdown_extensions:
  - plantuml_markdown:
      server: http://plantuml:8080
  .
  .

docsフォルダを作成して、その中にindex.mdを用意します。

詳細はmkdocstringsのドキュメントを見てもらえばわかると思いますが、下記のような感じでmarkdownとして記入すれば、mkdocsのドキュメントにdocstringの内容がいい感じに反映されます。

index.md
# index
:::python_project_with_mkdocs.sample_calc

後はこれでdocker compose upして、localhost:8000にアクセスするとこんな感じででるようになります。

docstrings on mkdocs

最終的には下記のディレクトリ構成になります。

.
├── Dockerfile
├── README.md
├── api-docs
│   ├── Makefile
    .
    .
├── docker-compose.yml
├── docs
│   ├── index.md
│   └── tags.md
├── mkdocs.yml
├── poetry.lock
├── pyproject.toml
├── python_project_with_mkdocs
│   ├── __init__.py
│   ├── __pycache__
│   └── sample_calc.py
├── scripts
└── tests
    └── __init__.py

まとめ

以上でpoetryとmkdocsとsphinxを使ってpythonプロジェクトの雛形ができました。

poetryでpre-commitなどを入れているので、dev container化と合わせてさらに環境を進化させますので、そのときになったら改めて環境一式をのrepoを置いておきたいと思います。

そろそろ別の言語の環境も整備したいな〜と思いつつ、環境整備が楽しくなってしまっているので近いうちにオレオレ最強Python環境を作る記事も投稿するようにします。

まだまだ未熟者なので、誤りあったら指摘していただけると幸いです。

Discussion