Poetry で Python プロジェクトの開発環境を揃えてみた
Python は長らく v2 系と v3 系の混在とか、マイナーバージョンが違うだけでも動かなくなる仕様変更とか、requirements.txt
にバージョン番号が書かれないため手元で再現不可能なプロジェクトとか、Python 本体のイマイチポイントと、レベルの低い利用者が氾濫していることに起因する諸問題が多すぎて、個人的には好きじゃない言語。インデントの強制という仕組みは面白いのに、全体的に何か動作が遅いし、インタプリタ言語だからなのか構文が簡単だからなのか知らないが、その場しのぎで書かれたスクリプトみたいな粗製乱造コードが大量に散見される印象。「僕の環境では動いてます」なんて情報じゃ何にも解決しねえんだよどうしてお前はどこまでも自分目線でしか物を言えねえんだ、他人が見たり書いたりする可能性があるコードなら再現性が確立されたプロジェクトを作らんかいこのボケ!
ということで、自分が Python を書く時は Pipenv を使って Python 本体のバージョンを固定したり依存パッケージのバージョンを明記したりしてきたのだが、今回は Poetry という別のツールを試してみる。コチラの方が高機能だそうだがどうだろう。
- 参考 : Poetry - Python dependency management and packaging made easy
- 参考 : Poetry documentation (ver. 1.1.6 日本語訳)
- 参考 : ゼロから学ぶ Python
Poetry をインストールする
今回は WSL2 Ubuntu 20.04.4 LTS にて環境を構築していく。事前の環境はこんな感じ。
$ type python
-bash: type: python: 見つかりません
$ type python3
python3 は /usr/bin/python3 です
$ python3 -V
Python 3.8.10
$ type pip
pip は /usr/bin/pip です
$ pip -V
pip 20.0.2 from /usr/lib/python3/dist-packages/pip (python 3.8)
$ type pip3
pip3 は /usr/bin/pip3 です
$ pip3 -V
pip 20.0.2 from /usr/lib/python3/dist-packages/pip (python 3.8)
python
(python2
) はもう標準ではインストールされていないみたい。pip
は pip3
と同じ実体を示しているが、コマンドを打つ時は python3
と明言してあげる方が良いな。
Poetry のインストールは以下のようにする。python
ではなく python3
コマンドで実行している。
$ curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python3 -
Retrieving Poetry metadata
This installer is deprecated. Poetry versions installed using this script will not be able to use 'self update' command to upgrade to 1.2.0a1 or later. It is recommended to use https://install.python-poetry.org instead. Instructions are available at https://python-poetry.org/docs/#installation
# Welcome to Poetry!
This will download and install the latest version of Poetry,
a dependency and package manager for Python.
It will add the `poetry` command to Poetry's bin directory, located at:
$HOME/.poetry/bin
This path will then be added to your `PATH` environment variable by
modifying the profile files located at:
$HOME/.profile
$HOME/.bash_profile
You can uninstall at any time by executing this script with the --uninstall option,
and these changes will be reverted.
Installing version: 1.1.14
- Downloading poetry-1.1.14-linux.tar.gz (97.91MB)
Poetry (1.1.14) is installed now. Great!
To get started you need Poetry's bin directory ($HOME/.poetry/bin) in your `PATH`
environment variable. Next time you log in this will be done
automatically.
To configure your current shell run `source $HOME/.poetry/env`
ということでインストール完了。~/.bashrc
に以下を追記した。
# ~/.bashrc
export PATH="${PATH}:${HOME}/.poetry/bin"
Poetry のバージョンを確認してみる。
# その場で読み込み
$ source "${HOME}/.poetry/env"
$ poetry -V
Poetry version 1.1.14
コレで OK。
Poetry でプロジェクトを作ってみる
Poetry でプロジェクトを作ってみる。$ poetry new
は、$ go mod init
とか $ cargo new
とか $ zig init-exe
とかみたいに、雛形ファイルがいくつか生成される感じみたい。
$ Poetry プロジェクトを作る
$ poetry new practice-poetry-project
Created package practice_poetry_project in practice-poetry-project
# 以下のようにファイルが生成されている
$ tree ./practice-poetry-project/
./practice-poetry-project/
├── README.rst
├── pyproject.toml
├── practice_poetry_project
│ └── __init__.py
└── tests
├── __init__.py
└── practice_poetry_project.py
2 directories, 5 files
プロジェクト構成は次の資料が参考になる。
- 4.7. プロジェクト構成 - ゼロから学ぶ Python
- Poetry が作る環境は基本的に、The Hitchhiker's Guide to Python に従っている
- 基本的な使い方 - Poetry documentation (ver. 1.1.6 日本語訳)
- 親ディレクトリはハイフンケース、
pyproject.toml
内のname
もハイフンケース。子ディレクトリにソースを置くスネークケースのディレクトリを作るのが通常
- 親ディレクトリはハイフンケース、
時たま、Git のリポジトリ名までスネークケースにしないといけないと思い込んでる奴がいるけど、Git と Python って何の関係もないし、上述のとおり代表的なプラクティスではプロジェクト名や親ディレクトリはケバブケースにするのが普通で、Google なんかのリポジトリを見てもケバブケースは普通に登場している。Python の基礎知識も持たずに書いてるザコだと判断して見下していくのでよろしく。
ちなみに、既存ディレクトリ内で $ poetry init --no-interaction
と書いても、pyproject.toml
を出力してくれる。コチラは $ npm init -y
に近いかな。ただし、$ poetry new
でプロジェクトを構築すると pytest
がセットでインストールされるが、$ poetry init
では何もインストールされないのでその点は注意。プロジェクト構成などの雛形を Python 標準に合わせたいのであれば $ poetry new
で始める方が良いかな。
Poetry でパッケージ管理する
例えば mecab-python3
をインストールしたいな、という場合は $ poetry add
でインストールする。
$ poetry add mecab-python3
Using version ^1.0.5 for mecab-python3
Updating dependencies
Resolving dependencies... (6.0s)
Writing lock file
Package operations: 8 installs, 0 updates, 0 removals
• Installing pyparsing (3.0.9)
• Installing attrs (22.1.0)
• Installing more-itertools (8.13.0)
• Installing packaging (21.3)
• Installing pluggy (0.13.1)
• Installing py (1.11.0)
• Installing wcwidth (0.2.5)
• Installing pytest (5.4.3)
# pyproject.toml に追記される
$ cat ./pyproject.toml
[tool.poetry]
name = "practice-poetry-project"
version = "0.1.0"
description = ""
authors = ["Neos21 <neos21@gmail.com>"]
[tool.poetry.dependencies]
python = "^3.8"
mecab-python3 = "^1.0.5" # ← ココ
[tool.poetry.dev-dependencies]
pytest = "^5.2"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
npm における dependencies
と devDependencies
と同様で、開発者のみ利用するツールをインストールする際は -D
オプションを付けることで [tool.poetry.dev-dependencies]
ブロックの方に記述される。
# mypy は型ヒントを入れる、flake8 は静的チェック、black は自動フォーマッタ、isort は import のソート用
$ poetry add mypy flake8 black isort -D
Using version ^0.971 for mypy
Using version ^5.0.4 for flake8
Using version ^22.6.0 for black
Using version ^5.10.1 for isort
Updating dependencies
Resolving dependencies... (2.6s)
Writing lock file
Package operations: 13 installs, 0 updates, 0 removals
• Installing click (8.1.3)
• Installing mccabe (0.7.0)
• Installing mypy-extensions (0.4.3)
• Installing pathspec (0.9.0)
• Installing platformdirs (2.5.2)
• Installing pycodestyle (2.9.1)
• Installing pyflakes (2.5.0)
• Installing tomli (2.0.1)
• Installing typing-extensions (4.3.0)
• Installing black (22.6.0)
• Installing flake8 (5.0.4)
• Installing isort (5.10.1)
• Installing mypy (0.971)
black
については pyproject.toml
に [tool.black]
というブロックを書けば、設定ファイルを増やさずに black
用の設定が書ける。flake8
については pyproject-flake8
というラッパーを使えば可能といわれているが、自分が試したところエラーが出てしまい正常に動作しなかった。ラッパー自体がまだアルファ版なので、素直に .flake8
設定ファイルを別個で作ってやることにした。
依存パッケージをインストールすると poetry.lock
というファイルができるが、コレは公式がいうには Git 管理に含めるべき、だそうだ。pyproject.toml
にはデフォルトではキャレット ^
記号でバージョン番号が記載されるのでそれでも大抵の場合は問題なさそうだが、より厳密に環境情報を残せるだろう。
Poetry のちょっと残念なところは、Pipenv の [scripts]
ブロック (npm でいう package.json
の scripts
) 相当のスクリプトを書ける機能がないところ。[tool.poetry.scripts]
というブロックは用途が異なるのだ。その点だけ注意。
Poetry で作られた仮想環境で作業する
Poetry も Pipenv と同じく、$ poetry shell
と書けば指定の Python バージョンでの仮想環境が立ち上がって作業できるようになる。その他、$ poetry run
を使えばシェルを起動することなく実行することもできる。
$ poetry shell
Spawning shell within /home/neo/.cache/pypoetry/virtualenvs/practice-poetry-project-NzgxAWMQ-py3.8
. /home/neo/.cache/pypoetry/virtualenvs/practice-poetry-project-NzgxAWMQ-py3.8/bin/activate
$$ type python3
python3 は /home/neo/.cache/pypoetry/virtualenvs/practice-poetry-project-NzgxAWMQ-py3.8/bin/python3 です
# 抜ける時は普通に exit
$$ exit
ちなみに python3
ではなく python
コマンドも仮想環境の Python を指すように設定されている。
# 自分が作ったモジュールを実行するならこんな感じ
$ poetry shell
$$ python -m practice_poetry_project
# もしくは以下のように一発で実行
$ poetry run python -m practice_poetry_project
# 開発系のツールを実行する際も次のようにやれば良い
$ poetry run python -m mypy ./
$ poetry run python -m flake8 ./
$ poetry run python -m black ./
$ poetry run python -m isort ./
$ poetry run python -m pytest
こんな感じ。
なお、git clone
などしてきた Poetry プロジェクトで環境構築する際は $ poetry install
だけ最初に打てば良い。
Pipenv は Pipfile
という設定ファイルを作るが、Poetry が作る pyproject.toml
は PEP 518 で規定されている Python 標準の設定ファイル形式だ。今後はコチラに揃えておくと良いだろう。