pyproject.toml の書き方完全ガイド

概要

Python のプロジェクト設定は、かつて setup.py / setup.cfg / requirements.txt / MANIFEST.in / 各ツールごとの .ini ファイルへとバラバラに散っていました。これを 1つのファイルに集約する標準フォーマットpyproject.toml です。

本記事は入門者向けに、pyproject.toml の役割・各セクションの意味と書き方を、コピペで動くサンプルとともに解説します。

pyproject.toml とは

pyproject.tomlPEP 518 で導入され、PEP 621 でメタデータの書き方が標準化された、TOML 形式の設定ファイルです。役割は大きく3つあります。

  1. ビルドの入口を宣言する[build-system]
  2. プロジェクトのメタデータを宣言する[project]
  3. 各種ツールの設定を集約する[tool.*]

パッケージ配布をしない人でも、ruffpytestmypy の設定置き場として使う価値があります。

最小構成のサンプル

これだけあれば 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-dependenciespip 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.tomldependencies は「抽象的な依存宣言」、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ファイルに集まる心地よさが、すぐに実感できるはずです。

\ 最新情報をチェック /

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください