パッケージの設定とメタデータにはpyproject.tomlファイルを使用します。#

pyproject.toml takeaways

  1. インストール可能なPythonパッケージに必要なテーブルは2つだけです: [build-system] と [project] です。 [project] テーブルにはパッケージのメタデータが格納されます。

  2. There are two required fields in the [project] table: name= and version=.

  3. Add metadata to the classifiers section of your pyproject.toml file to make it easier for users to find your project on PyPI.

  4. [project] テーブルに分類を追加するときは、 PyPIの分類ページ にある有効な値のみを使用してください。 ここで無効な値を指定すると、パッケージをビルドするときやPyPIに公開するときにエラーが発生します。

  5. There is no specific order for tables in the pyproject.toml file. However, fields need to be placed within the correct table sections. For example requires = always needs to be associated with the [build-system] table.

pyproject.tomlファイルについて#

Every modern Python package should include a pyproject.toml file. For pure Python packages, this file replaces the setup.py and/or setup.cfg file to describe project metadata.

If your project isn’t pure Python, you might still require a setup.py file to build the non-Python extensions. However, a pyproject.toml file should still be used to store your project’s metadata.

チュートリアル

setup.py または setup.cfg ファイルから移行しており、サポートが必要な場合は、このチュートリアルを確認してください。 ビルド要件を指定し、メタデータは pyproject.toml と呼ばれます

.toml フォーマットについて#

The pyproject.toml file is written in TOML (Tom's Obvious, Minimal Language) format. TOML is an easy-to-read structure based on key/value pairs. Each section in the pyproject.toml file contains a [table identifier]. Below that table identifier are key/value pairs that support configuration for that particular table.

  • [build-system] 以下はtoml言語ではテーブルとみなされます。

  • Within the build-system table, requires = is a key.

  • requires に関連する値は、値 "hatchling" を含む配列です。

[build-system]
requires = ["hatchling"]

パッケージのビルド時にpyproject.tomlがどのように使用されるか#

PyPIに公開すると、各パッケージにメタデータがリストされていることに気づくでしょう。pyOpenSciパッケージ の一つである xclim を見てみましょう。PyPIのランディングページには、pythonやメンテナ情報など、パッケージに関するメタデータが表示されていることに注目してください。PyPIは、Xclimのメンテナ pyproject.toml file によって正しい構文と分類子を用いて定義されたメタデータを入力することができます。xclimパッケージがビルドされるとき、このメタデータは配布ファイルに変換され、PyPIがメタデータを読み込んでウェブサイトに出力できるようになります。

xclimパッケージのPyPI左サイドバーの画像です。一番上のセクションにはClassifierとあります。その下に、開発状況、対象読者、ライセンス、自然言語、オペレーティングシステム、プログラミング言語、トピックなどの項目があります。 これらの各セクションの下には、さまざまな分類オプションがあります。 " width="300px">

pyproject.tomlにclassifierセクションを追加してパッケージがビルドされると、ビルドツールはメタデータをPyPIが理解できる形式に整理し、PyPIのランディングページに表示します。 これらの分類子により、ユーザはサポートするpythonのバージョンやカテゴリなどでパッケージをソートすることもできます。#

pyproject.tomlファイルを使用する利点#

パッケージのメタデータを人間が読める pyproject.toml 形式で含めると、GitHubのリポジトリでプロジェクトのメタデータを見ることができます。

Setup.py は、複雑なパッケージのビルドに便利です。

パッケージのビルドとメタデータを管理するために setup.py を使うことは パッケージ開発に問題を引き起こす可能性があります 。 Python パッケージのビルドが複雑な場合、setup.py ファイルが必要になるかもしれません。 このガイドでは複雑なビルドは扱いませんが、将来的には複雑なビルドを扱うリソースを提供する予定です。

Optional vs. required pyproject.toml file fields#

pyproject.toml ファイルを作成するとき、使用できるメタデータフィールドがたくさんあります。 以下では、PyPI での公開とユーザがあなたのパッケージを見つけることをサポートする、特定のフィールドを提案します。

プロジェクトの全メタデータ要素の概要は、こちらをご覧ください。

[project] テーブルの必須フィールド#

上述したように、 pyproject.toml ファイルはパッケージを適切にビルドするために name と version フィールドを持つ必要があります:

  • name: プロジェクトの名前を文字列で指定します。

  • version: プロジェクトのバージョンです。 バージョン管理に SCM ツール (git タグを使用してバージョンを決定する) を使用している場合は、このバージョンは動的なものになります (詳細は後述します)。

[project] テーブルに含めるオプションフィールド#

以下のメタデータキーも追加することを強くお勧めします。 これらのフィールドを追加することで、あなたのパッケージがどのような構造になっているのか、どのプラットフォームをサポートしているのか、どのような依存関係が必要なのかを明確にすることができます。

  • Description: これはあなたのパッケージの短い一行説明です。

  • Readme: 長い長い説明には README.md ファイルへのリンクが使われます。 この情報はあなたのパッケージのPyPIランディングページで公開されます。

  • Requires-python (pipで使用): これはpipが使用するフィールドです。 ここでは、Python 2.xと3.xのどちらを使っているかをインストーラに伝えます。 ほとんどのプロジェクトは3.xを使うでしょう。

  • ライセンス: 使用しているライセンス

  • Authors: パッケージの原作者です。 作者がメンテナと異なることもあります。 また、同じ場合もあります。

  • Maintainers: これを入力するかどうかを選択できます。 各作者やメンテナーの名前、Eメール、メールアドレスなどのサブ要素を持つリストを使って、この情報を入力することができます。

authors = [
    {name = "Some Maintainer", email = "some-email@pyopensci.org"},
]
  • project.dependency: すべてのパッケージが依存関係を必要とするわけではないため、依存関係グループはオプションです。ただし、プロジェクトに特定の依存関係がある場合は、このセクションを pyproject.toml に含めてください。 pyproject.toml ファイルで宣言された依存関係は、プロジェクトのインストール時に uv または pip によってインストールされます。

  • project.optional-dependencies: Optional or feature dependencies will be installed if someone runs python -m pip install projectname[feature]. Use this array to declare dependencies that add specific features to your package that are not installed by default when a user runs uv sync or python -m pip install packagename.

  • dependency-groups: 依存関係グループは、寄稿者または開発者がパッケージで作業する必要があるパッケージとツールを整理します。これらの依存関係には、テスト、リンター、コード フォーマッタを構築および実行するためのツールが含まれる場合があります。これはオプションですが、依存関係を整理してインストールするために強く推奨される方法です。このセクションは、requirements.txt ファイルを置き換えることができます。 これらをパッケージに追加する方法については、こちらの PyPA ガイドをご覧ください。

  • keywords: これらはPyPIのランディングページに表示されるキーワードです。 人々があなたのパッケージを検索するときに使う言葉だと考えてください。

  • classifiers: The classifiers section of your metadata is also important for the landing page of your package in PyPI and for filtering of packages in PyPI. A list of all options for classifiers can be found here. Some of the classifiers that you should consider including

    • 開発状況

    • 対象読者

    • トピック

    • プログラミング言語

pyproject.tomlファイルの高度なオプション#

  • [project.scripts] (Entry points): エントリーポイントは任意です。 パッケージでホストされている特定のスクリプトを実行するコマンドラインツールがある場合、そのスクリプトを(Pythonシェルではなく)コマンドラインで直接呼び出すためのエントリポイントを含めることができます 。

    • 以下は、エントリーポイントスクリプトを持つパッケージ の例である。 そのパッケージには、一連のタスクを実行するいくつかのコアスクリプトが定義されていることに注目してほしい。 pyOpenSciはこれらのスクリプトを使ってメタデータを処理しています。

  • Use Dynamic Fields If you have fields that are dynamically populated. For example, you may wish to automatically update your package's version using Git tags (SCM/version control-based versioning). Example: dynamic = ["version"]

pyproject.tomlファイルに依存関係を追加#

Required dependencies#

A requirements.txt file has been traditionally used to specify dependencies, but modern practice puts these in the pyproject.toml file. Required dependencies are specified under the [project] section as a list of strings:

[project]
...
...
...

dependencies = [
    "dependency-package-name-1",
    "dependency-package-name-2",
    "pandas",
    "xarray",
    "geopandas",
    "matplotlib"
]

Optional dependencies#

Optional dependencies are specified under the [project.optional-dependencies] section and are intended to give users options for including additional dependencies with their installation. Optional dependencies are collected together as a list of strings and assigned to a name:

[project.optional-dependencies]
plot = ["bokeh"]
test = ["pytest", "pytest-cov"]
docs = ["sphinx", "pydata-sphinx-theme"]

Named dependency lists can be invoked by users on installation to include those specific dependencies on installation. Here is an example installing the test and docs dependencies using pip:

  • python -m pip install examplePy[test,docs]

Other installation tools tend to follow a similar pattern where optional dependencies are concatenated as a list to the package name.

Dependency Groups#

Dependency groups are a way to group package requirements in the pyproject.toml file but exclude them in the project metadata when it is built. Because it is not included in the project metadadata, users will not be able to invoke dependency groups when installing from a package index such as PyPI, but they can be accessed by developers who have all the project data (e.g. through cloning a repository). Optional dependencies are intended for package consumers and dependency groups are intended for package maintainers and contributors.

To add development dependencies to your build, add a [dependency-groups] array to your pyproject.toml file. Then specify dependency groups as follows:

[dependency-groups]
test = [
    "pytest",
    "pytest-cov"
]

lint = [
    "black",
    "flake8",
    "ruff"
]

docs = [
    "sphinx",
    "pydata-sphinx-theme"
]

One of the capabilities that dependency groups have is the ability to make composition groups. For example, dev dependency group could be composed of a test dependency group and a lint dependency group:

[dependency-groups]
...
...
...

dev = [
    {include-group = "test"},
    {include-group = "lint"}
]

To access groups using pip (requires pip 25.1 or higher), you can invoke them during installation like this:

  • python -m pip install --group dev

再帰的依存関係

再帰的依存関係のセットをセットアップすることもできます。 詳しくはこのブログ記事を参照。

hatchlingを使用してビルドするpyproject.tomlの例#

以下は Python プロジェクトのビルド設定の例です。 このパッケージの設定例では、 パッケージの sdist と wheel をビルドするのに hatchling を使っています。

# pyproject.toml example build setup to use hatchling and hatch_vcs
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "examplePy"
authors = [
    {name = "Some Maintainer", email = "some-email@pyopensci.org"},
]
maintainers = [
    {name = "All the contributors"},
]
description = "An example Python package used to support Python packaging tutorials"
keywords = ["pyOpenSci", "python packaging"]
readme = "README.md"
license = "BSD-3-Clause"
classifiers = [
    # How mature is this project? Common values are
    "Development Status :: 4 - Beta",

    # Indicate who your project is intended for
    "Intended Audience :: Developers",
    "Topic :: Software Development :: Build Tools",
    "Programming Language :: Python :: 3 :: Only",
    "Programming Language :: Python :: 3.10",
    "Programming Language :: Python :: 3.11",
]
dependencies = [
    "dependency-package-name-1",
    "dependency-package-name-2",
    "pandas",
    "xarray",
    "geopandas",
    "matplotlib"
]

[dependency-groups]
test = [
    "pytest",
    "pytest-cov"
]

lint = [
    "black",
    "flake8",
    "ruff"
]

docs = [
    "sphinx",
    "pydata-sphinx-theme"
]

dev = [
    {include-group = "test"},
    {include-group = "lint"}
]

このファイルには依存関係が指定されています。

setuptoolsを使ってビルドするpyproject.tomlの例#

作者やキーワードなどを含むパッケージのメタデータも読みやすいです。 下の図は、異なるビルドシステム(setuptools)を使った同じTOMLファイルです。 このパッケージのビルドに必要なツールを入れ替えるのがいかに簡単かに注目してください!

このパッケージのセットアップ例では:

  • パッケージのsdistとwheel をビルドするための setuptools 。

  • setuptools_scm は、バージョン管理タグを使ってパッケージのバージョン更新を管理します。

以下の例では、[build-system] が最初の値のテーブルです。 このテーブルには2つのキーがあり、ビルドバックエンドAPIとそれを含むパッケージを指定します:

  1. requires =

  2. build-back-end =

[project]
name = "examplePy"
authors = [
    {name = "Some Maintainer", email = "some-email@pyopensci.org"},
]
maintainers = [
    {name = "All the contributors"},
]
description = "A setuptools example Python package used to support Python packaging tutorials"
keywords = ["pyOpenSci", "python packaging"]
readme = "README.md"
license = "BSD-3-Clause"
classifiers = [
    "Programming Language :: Python :: 3",
    "Operating System :: OS Independent",
    "Intended Audience :: Science/Research",
]
dependencies = []
dynamic = [
    "version",
]


[build-system]
requires = [
    "setuptools>=80",
    "setuptools-scm",
    "wheel",
]
build-backend = "setuptools.build_meta"


[tool.setuptools]
# Allow the package to be used directly from a zip archive.
zip-safe = true

# Do not automatically include non-Python package data in the wheel.
include-package-data = false

[tool.setuptools_scm]
write_to = "src/examplePy/_version.py"
version_scheme = "release-branch-semver"


[project.optional-dependencies]

test = [
    "pytest",
    "numpy",
    "pandas",
    "ruff",
]

contrib = [
    "pre-commit>=4.1.0",
]