パッケージ管理したい(poetry

// プロジェクトの初期化
$ poetry new プロジェクト名

// パッケージ管理
$ poetry add pandas matplotlib
$ poetry add --group=dev ipykernel pytests commitizen ruff
$ poetry add --group=docs sphinx_book_theme myst_parser

// poetry.lockにある依存関係をインストール
$ poetry install

// 仮想環境を起動
$ poetry shell         # poetry < 2.0.0
$ poetry env activate  # poetry >= 2.0.0

// パッケージをビルド
$ poetry build

// パッケージをリポジトリに公開
$ poetry publish

poetryはPythonのパッケージ管理とパッケージ公開できるツールです。 pyproject.tomlpoetry.lockの2つのファイルを使って依存関係を管理し、仮想環境も同時に作成できます。

参考

Pythonのパッケージ管理ツールはいろいろ存在しています。 おそらく複雑な歴史的経緯もあって、全体像を把握&理解することはかなり難しそうですが、僕が通ってきた道には次のようなパッケージがありました。

標準モジュール:

pip / venv

仮想環境:

virtualenv / pyenv / pipenv

パッケージ公開:

twine

これらのパッケージを組み合わせて、開発環境を整える必要がありました。 多くの先達たちが、その組み合わせのベストプラクティス的なものをブログ記事/Qiita記事などで紹介していました。

このようなPython世界観の中でpoetryが登場しました。 2020年ころに使いはじめてみたところ、仮想環境の構築、依存関係の管理、リポジトリへの公開までの一連のステップがオールインワンで完結することがわかり、常用することに決めました。

最近は2024年ころに登場した、より高速だというuvも使いはじめてみました。

インストールしたい(pipx install poetry

$ pipx install poetry
$ which poetry
~/.local/bin/poetry

$ poetry --version
Poetry (version 1.8.2)

$ pipx inject poetry poetry-plugin-export

公式ドキュメントではpipxを使った方法が推奨されています。 pip3のインストールは推奨されてないみたいです。

注意

Homebrewでもインストールできます。 このいずれかひとつの方法でインストールしてください。

シェル補完したい(poetry completions

$ poetry completions fish > ~/.config/fish/completions/poetry.fish

poetryコマンドのシェル補完が使えるようにしておくと便利です。 bashzshfishのシェルに対応しています。

ヒント

fishのシェル補完を使うと、シェルセッションで最初に実行したときにエラーが表示されます。 v1.2.0から存在しているバグ(poetry#5929)ですが、v1.5.0になっても修正されていません。 そのままでも使うことはできますが、以下のようにsdコマンドを使って置換して対処できます。

$ poetry completions fish | sd "'([^']+)''" '"$1"\'' > ~/.config/fish/completions/poetry.fish

エラーの原因は、以下のように__fish_seen_subcommand_fromが使われている部分の引数の文字列の囲み方に問題があるようです。

- < complete -c poetry -A -n '__fish_seen_subcommand_from 'cache clear'' -l all -d 'Clear all entries in the cache.'
---
+ > complete -c poetry -A -n '__fish_seen_subcommand_from "cache clear"' -l all -d 'Clear all entries in the cache.'

新規プロジェクトしたい(poetry new

$ poetry new PROJECT_NAME
Created package project_name in PROJECT_NAME

$ tree -a PROJECT_NAME
PROJECT_NAME
├── README.md
├── project_name
│   └── __init__.py
├── pyproject.toml
└── tests
    └── __init__.py

$ poetry new PROJECT_NAME
Destination ./PROJECT_NAME exists and is not empty

newコマンドでプロジェクトを初期化できます。 テスト関係のファイルも自動で生成されます。 同名のプロジェクトがすでに存在する場合は、エラーになります プロジェクト名を省略した場合は、エラーになります。

既存プロジェクトを使いたい(poetry init

$ cd プロジェクト名
$ poetry init

initコマンドで、既存のプロジェクトを初期化できます。 プロンプトの表示にしたがってプロジェクト情報(プロジェクト名、説明、作成者、バージョン番号、ライセンスなど)を入力します。 続けて、必要なパッケージに関するプロンプトが表示されるので、パッケージ名やバージョン番号を入力して、パッケージを選択します。 これらの設定はすべてpyproject.toml[tool.poetry]セクションに保存されます。 あとから直接編集できるので、間違えてしまっても大丈夫です。

パッケージを追加したい(poetry add

$ poetry add パッケージ名
$ poetry add パッケージ名 -E パッケージ名
$ poetry add --group=dev パッケージ名
$ poetry add --group=docs パッケージ名

必要なパッケージ名をpyproject.tomlに追記して、仮想環境(.venv)の中にインストールします。 -E / --extraオプションを使って、追加パッケージも指定できます。 パッケージは[tool.poetry.dependencies]のセクションに追記され、ロックファイル(poetry.lock)が生成されます。

開発環境を追加したい(--group=dev

$ poetry add --group=dev pytests
$ poetry add --group=dev commitizen
$ poetry add --group=dev jupyterlab

開発に必要なパッケージは--group=devに追加します。 (たしか)v1.3.0からグループ化する機能追加され、add -Dオプションが非推奨になりました。

ドキュメント環境を追加したい(--group=docs

$ poetry add --group=docs sphinx_book_theme
$ poetry add --group=docs myst_parser

ドキュメント作成に必要なパッケージは--groupd=docsに追加します。

パッケージをインストールしたい(poetry install

$ poetry install

poetry.lockにあるパッケージをインストールします。 poetry.lockがない場合は、pyproject.tomlにあるパッケージをインストールして、poetry.lockを生成します。

デフォルトでは{cache-dir}/virtualenvs/に設定されたパスの仮想環境を作成し、パッケージをインストールします。 virtualenvs.in-project = trueに設定した場合は、プロジェクト内の{project-dir}/.venv/に仮想環境を作成します。

パッケージ環境を確認したい(poetry check

$ poetry check
All set!

$ poetry check --lock
All set!

パッケージをビルドしたい(poetry build

$ poetry build
Building パッケージ名 (バージョン番号)
  - Building sdist
  - Built パッケージ名-バージョン番号.tar.gz
  - Building wheel
  - Built パッケージ名-バージョン番号-py3-none-any.whl

buildコマンドでパッケージをビルドできます。

パッケージを公開したい(poetry publish

// TestPyPIに公開
$ poetry publish -r testpypi
Publishing パッケージ名 (バージョン番号) to testpypi
 - Uploading パッケージ名-バージョン番号-py3-none-any.whl
 - Uploading パッケージ名-バージョン番号.tar.gz

// PyPIに公開
$ poetry publish
Publishing パッケージ名 (バージョン番号) to pypi
 - Uploading パッケージ名-バージョン番号-py3-none-any.whl
 - Uploading パッケージ名-バージョン番号.tar.gz

パッケージをビルドしてから公開します。 はじめて公開する場合は必ずTestPyPIでテストするのがよいです。 公開する前にリポジトリとAPIトークンの設定が必要です。

参考

僕のZennスクラップ「poetryを使ってpythonパッケージを作成する」に、Poetryを使ってパッケージを新規作成してPyPIで公開するまでの手順を整理しました。

TestPyPI/PyPIを設定したい

// testpypi という名前で TestPyPIを追加する
$ poetry config repositories.testpypi https://test.pypi.org/legacy/

// TestPyPIの個人ページで発行したAPIトークンを登録する
$ poetry config pypi-token.testpypi <your-token>

// PyPIの個人ページで発行したAPIトークンを登録する
$ poetry config pypi-token.pypi <your-token>

TestPyPI/PyPIに公開するために、APIトークンを設定する必要があります。 APIトークンは、それぞれのサービスの個人ページで発行したものをコピペしてください。

他にもさまざまな種類のリポジトリを設定できます。 詳しくはRepositoriesを参照してください。

現在の設定を確認したい(poetry config

$ poetry config --list
cache-dir = "~/Library/Caches/pypoetry"
experimental.new-installer = true
experimental.system-git-client = false
installer.max-workers = null
installer.modern-installation = true
installer.no-binary = null
installer.parallel = true
virtualenvs.create = true
virtualenvs.in-project = null
virtualenvs.options.always-copy = false
virtualenvs.options.no-pip = false
virtualenvs.options.no-setuptools = false
virtualenvs.options.system-site-packages = false
virtualenvs.path = "{cache-dir}/virtualenvs"  # ~/Library/Caches/pypoetry/virtualenvs
virtualenvs.prefer-active-python = false
virtualenvs.prompt = "{project_name}-py{python_version}"

現在の設定はpoetry config --listで確認できます。 デフォルトの設定は上記のようになっていました。 全体の設定は~/Library/Application Support/pypoetry/config.tomlに保存されます。 --localオプションをつけて設定した項目は、プロジェクト内のpoetry.tomlに保存されます。

注釈

全体の設定は、以前は~/Library/Preferences/pypoetry/config.tomlに保存されていました。 その状態でもまだ使えるようですが、将来的にはパスを変更したほうがよさそうです。

設定を変更したい

$ poetry config キー名 $ poetry config キー名  --local

変更可能な設定はPoetryドキュメントのAvailable Settingsを参照してください。 Poetry v1.2.0になって設定できる項目が増えました。

設定を削除したい

$ poetry config キー名 --unset
$ poetry config キー名 --unset --local

追加した設定を削除する場合はキー名に対して--unsetします。

プロジェクト内に仮想環境を作成したい

# 現在の設定値を確認する
$ poetry config virtualenvs.in-project
null

# 設定を有効にする
$ poetry config virtualenvs.in-project true

# 変更後の設定値を確認する
$ poetry config virtualenvs.in-project
true

仮想環境はvirtualenvs.pathで設定されたパスに作成されます。 デフォルトでは{cache-dir}/virtualenvsに設定されています。

virtualenvs.in-projecttrueにすると、その設定をカレントディレクトリの.venvに変更できます。 GitHub/GitLabなどを通じて複数のマシンで作業する場合は、この値を有効にしておくとよいです。

注意

すでに{cache-dir}/virtualenvs/に仮想環境がある場合は、一度削除(rm -r)してから作成しなおしてください。

システムのパッケージを使いたい

1$ poetry config virtualenvs.option.system-site-packages true

virtualenvs.option.system-site-packagestrueにすると、システムのPythonのsite-packagesにインストールが仮想環境から使えるようになります。 開発環境で使うパッケージ(pytest / black / commitizen / pysen)などを使うには、これを有効にしておいてもいいかもしれません。

ヒント

複数のPythonプロジェクトを持っていると、それぞれのプロジェクトの.venvにパッケージがインストールされます。 開発環境にだけ必要なパッケージを共通化することで、少しだけでもディスク節約になるかもしれません。

リポジトリとAPIトークンを設定したい

$ poetry config repositories.名前 URL
$ poetry config pypi-token.名前 "APIトークン"

名前の部分は任意の文字列で構いません。 以下にPyPITestPyPIの設定例を挙げておきます。

1# PyPIの設定
2$ poetry config pypi-token.pypi "PyPIのAPIトークン"
3
4# TestPyPIの設定
5$ poetry config repositories.testpypi https://test.pypi.org/legacy/
6$ poetry config pypi-token.testpypi "TestPyPIのAPIトークン"

PyPIはデフォルトの公開先になっているため、リポジトリの設定は必要ありません。 TestPyPIに公開する場合は、リポジトリのURLを設定する必要があります。 公開先のAPIトークンをそれぞれ事前に発行しておく必要があります。

リファレンス