私はこれまでPythonのパッケージ管理として pyenv + pipenv を主に使ってきました。が、最近はpipenvは色々あって使いづらさを感じていました。
pipenv lock
やpipenv sync
が遅い (気がする)- pipenv自体の更新が怪しかった (参考、今年に入って4月と6月にリリースされている模様)
乗り換える程の理由でもないのですが、代替となるツールは探しておかないとなあとふんわり思っていた頃、同僚がpoetryを使っていて良さそうでしたので、使い方をまとめながら紹介したいと思います。
poetry
poetryは、主にパッケージ依存関係の解決・インストール・更新と仮想環境の構築を行ってくれるコマンドラインツールです。上の通りpipenvなどが競合するツールになります。
インストール
pipで入れてしまうのが一番手軽です。
$ python --version Python 3.8.5 $ pip install poetry
プロジェクト作成
poetry new
でpoetryプロジェクトの標準的なディレクトリ構成が作られます。
- 既存のプロジェクトにpoetryで依存関係を管理する場合、newの代わりに
poetry init
を使います。
$ poetry new poetry-example Created package poetry_example in poetry-example $ cd poetry-example $ tree . ├── README.rst ├── poetry_example │ └── __init__.py ├── pyproject.toml └── tests ├── __init__.py └── test_poetry_example.py
このとき作成されるpyproject.tomlに追加するパッケージを記述していきます。
[tool.poetry] name = "poetry-example" version = "0.1.0" description = "" authors = ["ohke <...>"] [tool.poetry.dependencies] python = "^3.8" [tool.poetry.dev-dependencies] pytest = "^5.2" [build-system] requires = ["poetry>=0.12"] build-backend = "poetry.masonry.api"
仮想環境の構築
poetry install
または poetry update
とします。そうすると仮想環境 (virtualenv) が構築され、パッケージがインストールされます。
- デフォルトではdev-dependenciesのパッケージもインストールされます (
--no-dev
オプションで除くこともできます)
$ poetry install Creating virtualenv poetry-example-JGBVk9r8-py3.8 in /Users/ohke/Library/Caches/pypoetry/virtualenvs Updating dependencies Resolving dependencies... (0.2s) Writing lock file Package operations: 11 installs, 0 updates, 0 removals - Installing zipp (3.1.0) - Installing importlib-metadata (1.7.0) - Installing pyparsing (2.4.7) - Installing six (1.15.0) - Installing attrs (19.3.0) - Installing more-itertools (8.4.0) - Installing packaging (20.4) - Installing pluggy (0.13.1) - Installing py (1.9.0) - Installing wcwidth (0.2.5) - Installing pytest (5.4.3) - Installing poetry-example (0.1.0)
生成されるpoetry.lockファイルに依存パッケージが出力されます。このあたりはpyenvと同じですね。
$ tree . ├── README.rst ├── poetry.lock # ★ ├── poetry_example │ └── __init__.py ├── poetry_example.egg-info │ ├── PKG-INFO │ ├── SOURCES.txt │ ├── dependency_links.txt │ └── top_level.txt ├── pyproject.toml └── tests ├── __init__.py └── test_poetry_example.py
デフォルトではユーザホーム以下のキャッシュディレクトリに作成されますが、poetry config
で設定を書き換えることでカレントディレクトリに作ることもできます。以下では./.venvに作られています。
# 上で作った環境を削除 $ rm -rf /Users/ohke/Library/Caches/pypoetry/virtualenvs/poetry-example-JGBVk9r8-py3.8 $ poetry config --list cache-dir = "/Users/ohke/Library/Caches/pypoetry" virtualenvs.create = true virtualenvs.in-project = false virtualenvs.path = "{cache-dir}/virtualenvs" # /Users/ohke/Library/Caches/pypoetry/virtualenvs $ poetry config virtualenvs.in-project true $ poetry install Creating virtualenv poetry-example in /Users/ohke/dev/private/poetry-example/.venv ...
仮想環境上での実行
poetry run
で仮想環境でPythonコードを実行できます。上でインストールした仮想環境のパッケージがパスに含まれていることが確認できます。
poetry shell
で仮想環境上でシェルが立ち上がります
$ cat poetry_example/main.py import sys from pprint import pprint if __name__ == "__main__": pprint(sys.path) $ poetry run python poetry_example/main.py ['/Users/ohke/dev/private/poetry-example/poetry_example', ... '/Users/ohke/dev/private/poetry-example/.venv/lib/python3.8/site-packages', ...]
パッケージのインストール
パッケージを追加する場合、poetry add
を使います。これでpyproject.tomlとpoetry.lockが更新されます。
- pyproject.tomlを直接書き換えた場合は、
poetry update
で poetry.lockの更新 + 仮想環境へのインストール を行います - パッケージをアンインストールする場合は、
poetry remove
$ poetry add numpy Using version ^1.19.1 for numpy Updating dependencies Resolving dependencies... (1.6s) Writing lock file Package operations: 1 install, 0 updates, 0 removals - Installing numpy (1.19.1)
まとめ
概ねpipenvと変わらない機能を有することは確認できました。lockやsyncがどれだけ早くなるのか次第なところはありますが、現在pipenvを使っているプロジェクトを移行するまでのメリットは無さそうです。
去年12月に1.0がリリースされて以来、現在までバージョンアップも頻繁に行われているので、新しく作るシステムに関してはpoetryを使っていくのがいいのかな、という所感でした。