Poetryは、Pythonプロジェクトの依存関係・仮想環境・パッケージのビルドと公開を、pyproject.toml と poetry.lock の2ファイルで管理するツールです。2026年11月時点の最新は2.5.1(2026年9月20日公開)で、2.0(2025年1月)を境に poetry shell と poetry export が標準から外れ、依存の書き方もPython標準の [project] テーブルに移りました。本記事では2.5.1で実行した出力をもとに、基本コマンド、2.4以降の新設定でつまずく箇所、uvへの移行手順と選び方を整理します。
まとめ:Poetry 2.5で押さえる要点と採用判断
- Poetryは「宣言(pyproject.toml)」と「解決結果(poetry.lock)」を分け、推移的依存まで全員が同じ版を入れられるようにします。
- 最新は2.5.1。Poetry本体の動作にはPython 3.10以上が必要です(3.9のサポートは2.3.0で終了)。
- 2.0以降、
poetry shellはpoetry env activate、poetry install --syncはpoetry syncに置き換わり、poetry exportはプラグインの追加が必要になりました。 - 2.5.1の
poetry add --group devは、[tool.poetry.group]の無いプロジェクトではPEP 735の[dependency-groups]に書き込みます。 - 2.4.0の
solver.min-release-ageは、poetry addが書いた下限(=その時点の最新版)と衝突して解決に失敗することがあります。 - 新規プロジェクトはuvが第一候補です。同じ4依存のロックはPoetryの9.66秒に対しuvは1.48秒でした。既存のPoetryプロジェクトは急いで移る必要はなく、移るときは
migrate-to-uvがpoetry.lockの版を保ったままuv.lockを作ります。
Poetryの役割とpip・requirements.txtとの違い
python -m pip install -r requirements.txt は、ファイルに書かれたパッケージを今の環境へ入れるだけのコマンドです。requests とだけ書いてあれば、新しい環境ではそのとき制約を満たす版が選ばれるため、依存するcertifi・urllib3まで含めて実行時期によって組み合わせが変わります(既に入っている版は通常そのまま使われます)。pip freeze で固定すると、自分で選んだ依存と推移的な依存が1つのファイルに混ざります。
Poetryはこの2つを別ファイルに分けます。
| ファイル | 中身 | 誰が書くか |
|---|---|---|
| pyproject.toml | 直接使うパッケージと許容範囲 | 人(poetry addでも更新) |
| poetry.lock | 推移的依存を含む全パッケージの確定版とsha256 | Poetryが自動生成 |
2.5.1でrequestsを1つ追加すると、poetry.lockには5パッケージの確定版とsha256、末尾に lock-version = "2.1" と content-hash が記録されました。宣言を手で書き換えてロックを更新していないと、poetry install は pyproject.toml changed significantly since poetry.lock was last generated. Run `poetry lock` to fix the lock file. と表示して止まります。
仮想環境の作成もPoetryが受け持ちます。素のpipで仮想環境を作る手順はpip install flaskの手順と仮想環境の作成で扱っています。
Poetry 2.5.1のインストール手順とPython 3.10以上の要件
PyPIのpoetry 2.5.1のメタデータは Requires-Python: >=3.10,<4.0 です。macOS標準のPython 3.9では動きません。Python本体の版を切り替える方法はpyenvでPythonのバージョンを切り替える手順を参照してください。公式ドキュメントのインストール手順が案内する導入方法は、pipx・公式インストーラ・手動(専用のvenvにpipで入れる方法)の3つです。手元の開発機では次のどちらかを使います。
# pipx(Poetry専用の隔離環境に入る。更新は pipx upgrade poetry)
pipx install poetry
# 公式インストーラ(Linux・macOS・WSL)
curl -sSL https://install.python-poetry.org | python3 -
# 公式インストーラ(Windows PowerShell)
(Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | py -
# 確認
poetry --version
# Poetry (version 2.5.1)
公式インストーラで入れた場合の更新は poetry self update です。poetry: command not found になるときは、コマンドの置き場所(Linux・macOSは ~/.local/bin、Windowsは %APPDATA%\Python\Scripts)がPATHに入っていません。
プロジェクトで使うPoetryの最低版を決めるなら、pyproject.tomlに次のように書きます(2.0.0で追加)。版を1つに固定するなら "==2.5.1" と書きます。
[tool.poetry]
requires-poetry = ">=2.5"
プロジェクト作成から依存追加までの基本コマンド
poetry newとpoetry initが書き出すpyproject.toml
新規なら poetry new <名前>(src配置の雛形とtestsを作る)、既存ディレクトリなら poetry init(pyproject.tomlだけを作る)を使います。2.5.1の poetry new demo が出力したpyproject.tomlは次のとおりで、依存は [tool.poetry.dependencies] ではなくPEP 621の [project] に書かれます。
[project]
name = "demo"
version = "0.1.0"
description = ""
authors = [
{name = "Your Name",email = "[email protected]"}
]
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
]
[tool.poetry]
packages = [{include = "demo", from = "src"}]
[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
build-backend = "poetry.core.masonry.api"
requires-python には、Poetryが見つけたPython(ここでは3.12)が下限として入ります。1.x系の雛形は python = "^3.12" のように上限付きでしたが、2.0.0から >= が既定になりました。PATH上の python3 が3.14なら >=3.14 になるので、生成後に直します。
配布しないWebアプリやスクリプト集なら、[tool.poetry] に package-mode = false を書くと、プロジェクト自身のインストールが省かれます。[project] を使う場合も name と version は必須です。
poetry addが書く版の制約
poetry add requests を実行すると、pyproject.tomlには "requests (>=2.34.2,<3.0.0)" と書かれました。Poetry独自のキャレット指定(^2.34.2)は [project] では使えないため、poetry add が同じ意味の範囲指定に変換して書き込みます。左端の0でない桁が変わる更新を許さないため、0.x系のパッケージは上限が近くなり、httpxを追加したときは "httpx (>=0.28.1,<0.29.0)" でした。
poetry add requests # 最新版を下限に、次のメジャー未満
poetry add "django@~5.2" # チルダ:5.2.x のパッチ更新のみ
poetry add "pendulum>=2.0.5" # 上限なし
開発用依存の書き込み先とPEP 735の[dependency-groups]
テストやリンターのように本番で不要なものはグループに分けます。poetry new で作ったばかりのプロジェクトで poetry add --group dev pytest を実行すると、書き込み先はPEP 735の [dependency-groups] でした。
[dependency-groups]
dev = [
"pytest (>=9.1.1,<10.0.0)"
]
PEP 735の記法には2.2.0(2025年9月)で対応しました。書き込み先は既存の書き方で決まり、[tool.poetry.group] がある旧記法のプロジェクトでは、新しいグループも [tool.poetry.group.<名前>.dependencies] にキャレット指定(例 pluggy = "^1.6.0")で書かれます。
仮想環境の場所とPythonの版の切り替え
Poetryは最初の poetry install や poetry add で仮想環境を作ります。既定の作成先はキャッシュディレクトリの下(macOSなら ~/Library/Caches/pypoetry/virtualenvs)です。プロジェクト直下の .venv に作るなら、最初に設定を変えます。
poetry config virtualenvs.in-project true # ユーザー全体の設定。このプロジェクトだけなら --local を付ける
poetry env use 3.13 # Python 3.13 の仮想環境に切り替える
poetry env info -p # 使用中の仮想環境のパス
poetry env use に渡すPythonは、あらかじめPCに入っている必要があります。2.1.0で追加された poetry python install 3.13 を使えばPoetryがPythonを入手できますが、2.5.1の時点でも「experimental feature」の表示が付いています。
poetry runと[project.scripts]でのコマンド実行
poetry run は、仮想環境を有効化せずにその中でコマンドを実行します。ファイルを直接渡す(poetry run python main.py)なら設定は要りません。自作のコマンド名で呼ぶなら、[project.scripts] に「コマンド名 = “モジュール:関数”」を書き、poetry install を実行し直します。
# pyproject.toml
[project.scripts]
demo-cli = "demo.cli:main"
# src/demo/cli.py
import requests
def main():
print("requests", requests.__version__)
# poetry install のあと(requests 2.32.3 を入れた環境)
$ poetry run demo-cli
requests 2.32.3
コマンドはプロジェクト自身のインストール時に作られるため、package-mode = false では働きません。同じ設定で試すと poetry install は通り、poetry run pm-cli が Command not found: pm-cli で失敗しました。1.x系の [tool.poetry.scripts] でのコマンド定義は公式ドキュメントで非推奨です。
日常で使うコマンドの早見表
ロックと仮想環境を書き換えるコマンド(lock・update・install・sync)は後の章でまとめます。それ以外でよく使うものは次のとおりです。
| やりたいこと | コマンド |
|---|---|
| 依存を追加 | poetry add <名前> |
| 開発用に追加 | poetry add --group dev <名前> |
| 依存を削除 | poetry remove <名前> |
| 推移的依存を木で表示 | poetry show --tree |
| 新しい版がある依存を一覧 | poetry show --outdated |
| pyproject.tomlとロックの整合を検証 | poetry check |
| wheelとsdistを作る | poetry build |
| PyPIへ公開 | poetry publish |
Poetry 2.0のコマンド変更と代わりの手順
1.x系の最終版は1.8.5(2024年12月6日)です。1.x系の解説記事どおりに操作して詰まるのは、ほとんどが次のコマンドです。
| 1.x系の操作 | 2.x系での代わり | 変更版 |
|---|---|---|
poetry shell |
poetry env activate/poetry-plugin-shell |
2.0.0 |
poetry install --sync |
poetry sync |
2.0.0 |
poetry export |
poetry-plugin-exportを追加 | 2.0.0 |
poetry lock --no-update |
poetry lock(既定になった) |
2.0.0 |
poetry shell を実行すると Since Poetry (2.0.0), the shell command is not installed by default. と表示されます。代わりの poetry env activate は有効化コマンド(例 . /path/to/project/.venv/bin/activate)を表示するだけなので、シェルに実行させます。
# bash・zsh
eval $(poetry env activate)
# PowerShell
Invoke-Expression (poetry env activate)
# 従来の poetry shell を使い続ける場合
poetry self add poetry-plugin-shell
poetry-plugin-shellの最新は1.0.1です。poetry install --sync は動きますが、非推奨の警告が出ます。poetry export はプラグインが無いと The requested command export does not exist. で止まります。
poetry.lockの更新とコミット運用
lock・update・install・syncが変える範囲
似た名前のコマンドが4つあり、どれがロックファイルを書き換えるかで使い分けます。
| コマンド | poetry.lock | 仮想環境 |
|---|---|---|
poetry lock |
宣言の変更分だけ再解決 | 触らない |
poetry lock --regenerate |
全体を解き直す | 触らない |
poetry update [名前] |
範囲内の最新版へ更新 | 更新する |
poetry install |
読むだけ(無ければ生成) | 不足分を入れる |
poetry sync |
読むだけ(無ければ生成) | ロックに無いものを削除 |
2.0.0で poetry lock の既定が「既存の版を保つ」に変わり、古い手順書の --no-update は不要です。CIでは、余計なパッケージが残らない poetry sync の方が環境を再現できます。依存の更新をプルリクエストで受けたい場合はDependabotのdependabot.yml設定で package-ecosystem: "pip" を指定します。GitHubの対応エコシステム一覧はPoetryでも "pip" を指定するよう求めており、対応版はPoetry v2です。
poetry.lockのコミット要否とアプリ・ライブラリの違い
公式ドキュメントの基本操作は、アプリケーションではpoetry.lockをコミットするよう求めています。PyPIに公開するライブラリでは、利用者はロックファイルを無視して範囲内の最新版を使うため、固定したままテストしていると新しい依存での破損に作者が最後に気づきます。コミットするなら、定期的に poetry update してテストを回します。
requirements.txtとpylock.tomlへの書き出し
Dockerイメージやサーバーレス環境のように pip install -r requirements.txt しか使えない場所へは、ロックの内容を書き出して渡します。2.0.0以降はpoetry-plugin-export(最新1.10.1)を先に入れます。書き出したファイルは、READMEの指示どおり python -m pip install --no-deps -r requirements.txt で入れ、解決済みの依存をpipに解き直させません。
poetry self add poetry-plugin-export
poetry export -f requirements.txt --output requirements.txt
poetry export -f requirements.txt --without-hashes --with dev
poetry export -f pylock.toml --output pylock.toml
-f が受け付けるのは constraints.txt・requirements.txt・pylock.toml の3つです。pylock.tomlはPEP 751で標準化されたロックファイル形式で、Poetry 2.3.0とpoetry-plugin-export 1.10.0(ともに2026年1月18日)で書き出しに対応しました。Poetry自身が読むのはpoetry.lockなので、pylock.tomlはほかのツールへ渡す書き出し専用です。
既存のrequirements.txtプロジェクトをPoetryへ移す手順
移行は、pyproject.tomlを作って既存の依存を poetry add し直すだけです。入力は pip freeze の結果ではなく、直接使うパッケージだけのrequirements.txtにします。
poetry init -n --python ">=3.12"
# 1行に1パッケージ・コメントなし・環境マーカー(; python_version など)なしが前提
cat requirements.txt | xargs poetry add --lock
poetry install --no-root
requirements.txtに fastapi>=0.115・pandas・sqlalchemy>=2.0,<3・httpx の4行を置いて実行すると、制約を書いていた2つはそのまま、書いていなかった2つは "pandas (>=3.0.6,<4.0.0)"・"httpx (>=0.28.1,<0.29.0)" になりました。版を書かなかった依存は「今日の最新版が下限」になるため、上げたくない依存は元の版で下限を書いてから追加します。-r や --index-url の行は先に取り除きます。最後の --no-root を外すと、パッケージのフォルダが無いスクリプト集では Error: The current project could not be installed: No file/folder found for package s1 で止まりました。配布しないなら package-mode = false を書いておく方法もあります。
2.4・2.5で加わった設定とつまずく箇所
solver.min-release-ageとpoetry addの下限の衝突
2.4.0(2026年5月3日)で追加された solver.min-release-age は、公開から指定日数が経っていない版を依存解決の候補から外す設定です(公式ドキュメントの設定一覧)。公開直後に乗っ取られたパッケージを入れる攻撃への備えで、除外用の solver.min-release-age-exclude も同時に入りました。
前の章の移行直後のプロジェクトで poetry config --local solver.min-release-age 60 を設定して poetry lock --regenerate を実行すると、次のエラーで解決に失敗しました。
Because mig depends on pandas (>=3.0.6,<4.0.0) which doesn't match any versions, version solving failed.
pandas 3.0.6は2026年9月17日(UTC)の公開で、60日を経過していませんでした。poetry add は追加時点の最新版を下限に書くため、後から設定すると下限を満たす版がすべて除外されます。下限を手で下げるか、該当パッケージを除外するか、依存を追加する前に設定します。先に設定したプロジェクトでは poetry add pandas が "pandas (>=3.0.5,<4.0.0)" と、2026年7月22日公開の3.0.5を下限に書きました。
Dockerでvirtualenvs.create=falseにするときの2.5.0の変更
Dockerで仮想環境を作らずコンテナのPythonへ直接入れる場合、2.5.0からは、そのPythonが requires-python を満たさないとエラーで止まります。Python 3.12で >=3.13 のプロジェクトを扱った結果です。
Current Python version (3.12.13) is not allowed by the project (>=3.13).
Poetry cannot switch to a compatible Python version because virtualenv creation is disabled.
ベースイメージのPythonを上げ忘れたまま2.5系へ更新すると、ビルドがここで止まります。依存を先に入れてレイヤーキャッシュを効かせる例です。.dockerignore には .venv を書きます(コピーされた .venv があると、そちらへ入ります)。
FROM python:3.13-slim
ENV POETRY_VIRTUALENVS_CREATE=false
RUN python -m venv /opt/poetry && /opt/poetry/bin/pip install --no-cache-dir "poetry==2.5.1"
WORKDIR /app
COPY pyproject.toml poetry.lock ./
RUN /opt/poetry/bin/poetry install --only main --no-root --no-interaction
COPY . .
RUN /opt/poetry/bin/poetry install --only main --no-interaction
--only main は開発用グループを除き、--no-root はプロジェクト自身のインストールを省きます。GitHub Actionsでpoetry.lockのハッシュをキャッシュのキーにする設計はGitHub Actionsのキャッシュとkey設計で解説しています。
Poetryとuv・pip・condaの選び分け
機能の比較とロック速度の実測
| 観点 | pip+venv | Poetry 2.5 | uv | conda |
|---|---|---|---|---|
| ロックファイル | pylock.toml(実験的) | poetry.lock | uv.lock | conda-lock.yaml(26.5以降) |
| pyprojectの依存 | 読むのみ | [project] | [project] | 使わない |
| Python本体の導入 | しない | 実験的機能 | する | する |
| ビルド・公開 | 別ツール | build/publish | build/publish | conda-build |
| Python以外のライブラリ | 扱わない | 扱わない | 扱わない | 扱う |
fastapi・pandas・sqlalchemy・httpxの4依存を同じpyproject.tomlからロックし、各3回の中央値を取りました(2026年11月13日・Intel Mac・Python 3.12.13)。
| 条件 | Poetry 2.5.1 | uv 0.13.8 |
|---|---|---|
| キャッシュなし | 9.66秒 | 1.48秒 |
| キャッシュありで解き直し | 5.60秒 | 0.92秒 |
解き直しは poetry lock --regenerate と uv lock --upgrade です。依存を [project] に書いていればuvも同じpyproject.tomlを読めますが、[tool.poetry.dependencies] の旧記法では uv lock が0パッケージで終わりました。uvの使い方はuvとは?Pythonの環境構築・パッケージ管理の使い方、開発元AstralのOpenAIによる買収発表の経緯はOpenAIのAstral買収とuv・Ruff・tyのその後にまとめています。
Poetryからuvへ移す手順とmigrate-to-uvの変換結果
uvはpoetry.lockを読まないため、移るにはuv.lockを作り直します。migrate-to-uv(最新0.12.0・2026年4月8日)を使うと、pyproject.tomlの書き換えとロックを1回で済ませられます。
uvx migrate-to-uv --dry-run # 変換後のpyproject.tomlを表示するだけ
uvx migrate-to-uv # 書き換えてuv.lockを作る
uv sync --locked
旧記法のプロジェクト(python = "^3.12"・httpx = "^0.27.0"・[tool.poetry.group.dev.dependencies] に pytest = "^8.3")で実行すると、次のように変換されました。
[project]
requires-python = ">=3.12,<4"
dependencies = ["httpx>=0.27.0,<0.28"]
[dependency-groups]
dev = ["pytest>=8.3,<9"]
[tool.uv]
package = false
default-groups = "all"
ログには Locking dependencies with constraints from existing lock file(s) と出て、uv.lockのhttpx 0.27.2・pytest 8.4.2はpoetry.lockと同じでした。poetry.lockは削除されます(残すなら --keep-current-data)。
poetry new で作ったsrc配置のプロジェクトでは、Migrating build backend to Hatch, as package distribution is too complex to be expressed with uv. と警告が出て、ビルドバックエンドがpoetry-coreからhatchlingに置き換わりました。公開しているなら移行前後でwheelとsdistの中身を比べるか、--keep-current-build-backend でPoetryのビルド設定を残します。版制約の || は移行に失敗するため、対応表を見て先に書き換えてください。
プロジェクトの種類別の選び方
- 新規プロジェクト:uvを第一候補にします。Python本体の導入まで1つで済み、今回の4依存の測定ではロック時間がPoetryの約6分の1だったためです。
- 既にPoetryで回っているプロジェクト:移行の利点がロック速度だけなら急ぐ理由はありません。2.xへの更新(
[project]への移行とpoetry shellの置き換え)を先に済ませておけば、移るときもmigrate-to-uvで版を保ったまま移せます。 - PyPIへライブラリを公開するプロジェクト:
poetry build・poetry publish・poetry versionがそろっており、Poetryのままで不足はありません。uvへ移るとビルドバックエンドが変わる場合もあります。 - GDALやRのように、PyPIにwheelが無いPython以外のライブラリに依存する分析環境:condaを使います。PoetryもuvもPythonパッケージしか扱わず、OSレベルのライブラリは入れられません。
Poetryを新たに導入すべきでないのは、本体を動かすPython 3.10以上を用意できない環境と、requirements.txtしか受け付けないデプロイ先へのexportを運用しきれないチームです。後者ではロックとrequirements.txtの二重管理になり、導入前より悪化します。依存管理の選定を含めてPythonで業務システムを一から作る場合は、フルスクラッチ開発として相談を受けています。
よくある質問
Poetryとpipはどちらを使うべきですか?
複数人で開発する、またはCIや本番と同じ版をそろえたいならPoetry(またはuv)です。ロックファイルの要らない使い捨てのスクリプトなら、pipと仮想環境で足ります。
poetry shellが使えなくなったのはなぜですか?
Poetry 2.0.0でpoetry-plugin-shellという別プラグインに移ったためです。eval $(poetry env activate) を使うか、poetry self add poetry-plugin-shell で従来のコマンドを戻します。
PoetryでPythonのバージョンを変更するには?
requires-python を目的の版が入る範囲に直し、poetry env use 3.13、poetry lock、poetry install の順に実行します。古い仮想環境のまま先に poetry lock すると、Please change python executable via the "env use" command. で止まります。Pythonが未導入ならpyenvなどで先に入れます。
poetry.lockはGitにコミットすべきですか?
アプリケーションならコミットします。公開ライブラリでは利用者側でロックが無視されるため、依存を定期的に更新してテストします。
python -m pip install -r requirements.txtとpoetry installの違いは?
前者はrequirements.txtの指定と今の環境に入っている版をもとに解決するため、固定していない推移的依存は実行時期で変わります。poetry install はpoetry.lockの版とハッシュどおりに、プロジェクト専用の仮想環境へ入れます。