pyproject.toml の書き方完全ガイド
概要
Python のプロジェクト設定は、かつて setup.py / setup.cfg / requirements.txt / MANIFEST.in / 各ツールごとの .ini ファイルへとバラバラに散っていました。これを 1つのファイルに集約する標準フォーマットが pyproject.toml です。
本記事は入門者向けに、pyproject.toml の役割・各セクションの意味と書き方を、コピペで動くサンプルとともに解説します。
pyproject.toml とは
pyproject.toml は PEP 518 で導入され、PEP 621 でメタデータの書き方が標準化された、TOML 形式の設定ファイルです。役割は大きく3つあります。
- ビルドの入口を宣言する(
[build-system]) - プロジェクトのメタデータを宣言する(
[project]) - 各種ツールの設定を集約する(
[tool.*])
パッケージ配布をしない人でも、ruff や pytest、mypy の設定置き場として使う価値があります。
最小構成のサンプル
これだけあれば pip install . が通ります。
[build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "my-package" version = "0.1.0" description = "A small example package" requires-python = ">=3.9"
[build-system] で「ビルドに何が必要か」を、[project] で「このプロジェクトは何者か」を宣言します。この2つが中核です。
[build-system] セクション
[build-system] requires = ["hatchling"] build-backend = "hatchling.build"
requires— ビルドに必要なパッケージ。ビルド専用の隔離環境に自動インストールされます。build-backend— 実際にビルドを行うバックエンドのモジュール名。
代表的なバックエンドの選択肢は次の通りです。
| バックエンド | requires | build-backend |
|---|---|---|
| setuptools | ["setuptools>=61.0"] |
"setuptools.build_meta" |
| Hatchling | ["hatchling"] |
"hatchling.build" |
| Flit | ["flit_core>=3.4"] |
"flit_core.buildapi" |
| PDM | ["pdm-backend"] |
"pdm.backend" |
シンプルさ重視なら Hatchling か Flit、情報量重視なら setuptools が無難です。
[project] セクション
PEP 621 が定めた、ツール非依存の標準メタデータです。
[project]
name = "my-package"
version = "0.2.0"
description = "A short one-line description"
readme = "README.md"
requires-python = ">=3.9"
license = "MIT"
authors = [
{ name = "Your Name", email = "you@example.com" },
]
classifiers = [
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
]
dependencies = [
"requests>=2.28",
"click>=8.0",
]
[project.urls]
Homepage = "https://example.com"
Repository = "https://example.com/repo"
[project.optional-dependencies]
dev = [
"pytest>=7.0",
"ruff>=0.1",
"mypy>=1.0",
]
[project.scripts]
my-cli = "my_package.cli:main"
主要フィールドを整理します。
name/version— 名前と版数。description— 1行の説明。readme— README ファイルの指定。requires-python— 対応 Python バージョン。dependencies— 実行時に必要な依存。従来のrequirements.txtの役割を担います。optional-dependencies—pip install ".[dev]"のように追加インストールできる依存。project.scripts— コマンドラインのエントリポイント。project.urls— ドキュメント・リポジトリへのリンク。
バージョンを動的に扱う
[project] name = "my-package" dynamic = ["version"] [tool.hatch.version] path = "src/my_package/__init__.py"
__init__.py の __version__ を単一の情報源にできます。
[tool.*] セクション — ツール設定の集約
[tool.<ツール名>] は各ツールが自由に使える名前空間です。設定を集めると、リポジトリ直下の設定ファイルが激減します。
[tool.ruff] line-length = 100 target-version = "py39" [tool.ruff.lint] select = ["E", "F", "I"] ignore = ["E501"] [tool.pytest.ini_options] testpaths = ["tests"] addopts = "-ra -q" [tool.mypy] python_version = "3.9" strict = true ignore_missing_imports = true [tool.coverage.run] source = ["src"] branch = true
リンタ・型チェッカ・テストの設定を1ファイルに束ねられるのが、[tool.*] の恩恵です。
src レイアウトの推奨
配布するなら src/ 配下にコードを置く src レイアウトが推奨です。テストが誤って直下コードを import する事故を防げます。
my-package/
├── pyproject.toml
├── README.md
├── src/
│ └── my_package/
│ ├── __init__.py
│ └── cli.py
└── tests/
└── test_cli.py
setuptools で自動検出が効かない場合は次のように明示します。
[tool.setuptools.packages.find] where = ["src"]
確認方法
# 開発インストール(editable) pip install -e . # 開発用の追加依存も入れる pip install -e ".[dev]" # ビルドしてみる pip install build python -m build # メタデータの検証 pip install twine twine check dist/*
dist/ に .whl と .tar.gz が出力されれば、記述に大きな誤りはありません。
注意点
- TOML の文字列はダブルクォートが基本。配列の末尾カンマは許容されます。
dependenciesを固定しすぎると衝突しやすくなります。ライブラリは下限中心(>=)、アプリは lock ファイルで固定、が定石です。requirements.txtは今も有効。pyproject.tomlのdependenciesは「抽象的な依存宣言」、lock ファイルは「再現可能な固定」と役割が分かれます。- 新規プロジェクトは
setup.pyよりpyproject.tomlを第一選択にするのが現在の標準です。
まとめ
pyproject.tomlは Python プロジェクト設定の標準集約ファイル。- 中核は
[build-system]と[project]の2つ。 [tool.*]に Ruff / pytest / mypy の設定を集約するとリポジトリが片付く。- 配布するなら src レイアウト、確認は
pip install -e .とpython -m build。
まずは最小構成をコピペして pip install -e . を通すところから始めてみてください。設定が1ファイルに集まる心地よさが、すぐに実感できるはずです。
