Pythonプロジェクトの2つのパターン
- 使い捨てのスクリプトを書く
- パッケージとして整備しつつ外部のプログラムに使われるのを意識しつつ書く(メンテナンス性高い)
2.の用途として、自分が直面しているのはPyramidでWEBアプリを作るときです。
Pyramidは設定ファイルとして、PasteDeployを利用しています。
この設定ファイルから自パッケージ内のエントリポイントとなる関数名を取り出し、WSGIサーバーであるwaitress
やgunicorn
が利用することになります。
今回は2.のような場合について、どのようなディレクトリ構造がベストプラクティスなのかを調査しました。
ディレクトリ構造の研究
ディレクトリ構造を研究するために以下を参考にしました。
- プロジェクトの構造化 — The Hitchhiker's Guide to Python …①
- Quick Tutorial for Pyramid — The Pyramid Web Framework v1.9.2 …②
- requests/requests: Python HTTP Requests for Humans™ ✨🍰✨ …③
Pipenvは比較的新しいツールあまり言及している記事がありません。
実際、①と②にはPipenvは登場しません。
③には①と②に即したディレクトリ構造でありながら、かつPipenvを使って構成されていたので参考にしました。
基本的な構造
Pipenvを使わない場合
①を見るとディレクトリ構造は以下のようになっています。
* README.rst * LICENSE * setup.py * requirements.txt * sample/__init__.py * sample/core.py * sample/helpers.py * docs/conf.py * docs/index.rst * tests/test_basic.py * tests/test_advanced.py
sample
モジュールパッケージが自分が書くソースコードの中心となり、自分で書いたコードはこのディレクトリ以下に配置していくことになります。
setup.py
はsample
モジュールパッケージの依存関係を処理するためのもので、sample
でサードパーティのライブラリが必要な場合などはここで処理していきます。
編集可能モード
(②を順に見ていくと登場しますが)
pip
にはモジュールパッケージを編集可能モードとしてインストールできる機能があります。
例えば、上記のsample
モジュールパッケージでは
$ git clone git@github.com:kennethreitz/samplemod.git $ cd samplemod/ $ pip install -e .
とすることでsample
モジュールパッケージを編集可能モードでインストールできます。
編集可能モードでのインストールのメリットとしては:
- インストールで必要な工程を踏んでいるので、
sample
が必要としているサードパーティのライブラリを一遍にインストールできる - 編集可能モードの名前の通りいつでもモジュールパッケージに修正を加えることができる
- このモジュールパッケージを使うときは標準ライブラリのように扱える(どこでも
import sample
でインポートできる)
Pipenvも使う場合
「依存関係の処理はsetup.py
で行われるが、Pipenv
を使うメリットは何だろう?」と考えると、2つあると思います。
- 仮想環境(virtualenv)を作ってくれるので開発環境をシステム環境から隔離する
sample
モジュールパッケージが直接的に依存していないライブラリを管理する(例えば、デバッグツールとテストツールなど)
1.に関して、Pythonの標準ライブラリvenvを使えばできてしまえますが、モジュールパッケージを使う準備するときについでに仮想環境を作ってくれるので便利です。
2.に関して、実際にrequests
ライブラリ(③)を見てみると、Pipfile
にはほとんどテストツールやリンカ用のツールが記述されています。
Pipenvで編集可能モード
また、requests
ライブラリのPipfile
には以下のような記述があります。
[packages] "e1839a8" = {path = ".", editable = true, extras = ["socks"]}
これは、requests
ライブラリを編集可能モードとしてインストールした痕跡ですね。
Pipenv
ではpip
と同様に編集可能モードとしてモジュールパッケージをインストールすることができます。
$ git clone git@github.com:requests/requests.git $ cd requests/ $ pipenv install -e .
pip
と同様の使用感ですね。
一度、編集可能モジュールとしてインストールしてしまえばPipfileに記述されるので、別なシステムに移動した際でもPipenv
を使っていれば勝手に処理してくれるようになります。
実際、requests
のMakefile
には仮想環境(virtualenv)初期化用のコマンドが記述されています。
上記のpipenv install -e .
の代わりに
$ git clone git@github.com:requests/requests.git $ cd requests/ $ make init # pip install --upgrade pipenv && pipenv install --dev --skip-lock と同じ
とすれば、
- 仮想環境(virtualenv)を作る
- requestsモジュールパッケージを編集可能モードでインストールする(その依存関係にあるものも)
- テストツールやリンカ用のツールをインストールする
というのを一挙に終わらせてくれます。
あとは、pipenv shell
として仮想環境に入り開発に移ったり、pipenv run ほにゃらら
とコマンドを叩くだけです。楽ですね。
Docker
PipenvはPipfileの依存パッケージをシステムのPythonにインストールすることも容易です。
例えば、Pipenvが作る仮想環境の代わりにDockerで包んでしまう場合でも、
$ pipenv install --system
とすれば、Docker内ではmyprojectパッケージを標準ライブラリのように自由に使うことができそうです。
(やったことないけど)
感想
Pipfile
やsetup.py
とrequirements.txt
など同じことを目的にしてるように見えるファイルがたくさんあるので混乱しますが、
目的を適切に分けて考えてツールを使えば便利に使えそうでした。
困ったときはrequests
ライブラリのディクレトリ構造を参考にしていこうと思います。