読み込み中...

Pythonのdistutils廃止に伴う代替手段10選

distutils Python
この記事は約32分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

本記事のサンプルコードを活用して機能追加、目的を達成できるように作ってありますので、是非ご活用ください。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を満たす現役のプログラマチームによって監修されています。

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

●Pythonのdistutilsとは?廃止の衝撃

Pythonで長年親しまれてきたdistutilsモジュールが廃止されることになりました。

多くの開発者にとって、この動きは衝撃的なニュースかもしれません。

distutilsは、Pythonプロジェクトの配布とインストールを支援する標準ライブラリモジュールとして、長年にわたり重要な役割を果たしてきました。

distutilsの主な機能は、Pythonパッケージのビルド、配布、インストールを簡単に行えるようにすることでした。

多くの開発者がこのモジュールを利用して、自分のプロジェクトを他の人々と共有してきました。

しかし、技術の進歩とともに、distutilsにも限界が見えてきたのです。

○distutilsの役割と重要性

distutilsは、Pythonの標準ライブラリに含まれるモジュールとして、多くの開発者にとって最初の選択肢でした。

その主な役割は、Pythonパッケージの作成、配布、インストールを容易にすることでした。

具体的には、distutilsは次のような機能を提供していました。

  1. パッケージのメタデータ定義
  2. ソースコードの配布用アーカイブ作成
  3. パッケージのビルドとインストール
  4. C言語で書かれた拡張モジュールのコンパイルとリンク

多くの開発者がdistutilsを使用して、自分のプロジェクトを他の人々と共有できるようになりました。

また、distutilsはPython Package Index (PyPI)との連携も容易で、多くのオープンソースプロジェクトの基盤となっていました。

○distutils廃止の理由と影響

では、なぜdistutilsが廃止されることになったのでしょうか?

主な理由は、distutilsの設計が古くなり、現代のPython開発の要求に十分に応えられなくなったためです。

具体的には、次のような問題点がありました。

  1. 依存関係の管理が不十分
  2. ビルドプロセスのカスタマイズが難しい
  3. 新しいパッケージング標準(PEP 517, PEP 518)との互換性がない
  4. メンテナンスが困難になってきた

distutilsの廃止は、多くのプロジェクトに影響を与えます。

特に、distutilsに依存しているレガシーなプロジェクトは、代替手段への移行が必要になります。

また、distutilsを直接使用していなくても、setuptools等の関連ツールを通じて間接的に利用しているプロジェクトも影響を受ける可能性があります。

○あなたのプロジェクトは大丈夫?

distutilsの廃止は段階的に行われる予定です。

Python開発チームは、開発者に十分な移行期間を与えるため、次のようなタイムラインを設定しています。

  1. Python 3.10/distutilsの非推奨化が開始、警告メッセージが表示されるようになった
  2. Python 3.12/distutilsが標準ライブラリから削除される予定

皆さんのプロジェクトが安全かどうかを確認するには、次の点をチェックしてみましょう。

  1. プロジェクトがdistutilsを直接インポートしていないか
  2. setup.pyがdistutilsに依存していないか
  3. 使用しているサードパーティライブラリがdistutilsに依存していないか

もしこの点で問題があれば、早急に対策を検討する必要があります。

それでは、distutilsの代替手段について詳しく見ていきます。

distutilsの廃止は確かに大きな変更ですが、新しいツールはより強力で柔軟性が高いので、移行後はプロジェクトの管理がより効率的になると思います。

●distutils廃止後の10個の必須代替手段

Pythonの開発環境が大きく変わろうとしています。

distutilsの廃止に伴い、多くの開発者が新しいツールへの移行を余儀なくされています。

しかし、心配する必要はありません。

distutilsの後継として、より強力で使いやすい代替手段が登場しています。

ここでは、distutilsの機能を引き継ぎ、さらに進化させた10個の必須ツールをご紹介します。

○サンプルコード1:setuptools – 最強の後継者

setuptoolsは、distutilsの直接的な後継者として最も広く使われているツールです。

多くのプロジェクトがすでにsetuptoolsを採用しており、移行がスムーズに行えるでしょう。

setuptoolsの基本的な使い方を見てみましょう。

まず、setup.pyファイルを作成し、プロジェクトの設定を記述します。

from setuptools import setup, find_packages

setup(
    name="my_project",
    version="0.1",
    packages=find_packages(),
    install_requires=[
        "requests>=2.25.1",
        "pandas>=1.2.0",
    ],
)

この例では、プロジェクト名、バージョン、必要なパッケージを指定しています。

find_packages()関数を使用することで、プロジェクト内のすべてのパッケージを自動的に検出します。

setuptoolsを使ってプロジェクトをビルドするには、次のコマンドを実行します。

python setup.py sdist bdist_wheel

実行結果として、distディレクトリにソース配布物とwheelファイルが生成されます。

setuptoolsの利点は、distutilsとの互換性が高く、既存のプロジェクトを最小限の変更で移行できる点です。

また、依存関係の管理やエントリーポイントの設定など、より高度な機能も提供しています。

○サンプルコード2:poetry – 依存関係管理の革命児

poetryは、近年急速に人気を集めている新しいパッケージ管理ツールです。

依存関係の管理や仮想環境の作成を一元化し、開発ワークフローを大幅に改善します。

poetryを使ってプロジェクトを初期化するには、次のコマンドを実行します。

poetry init

対話形式でプロジェクトの設定を行った後、pyproject.tomlファイルが生成されます。

[tool.poetry]
name = "my_project"
version = "0.1.0"
description = ""
authors = ["Your Name <you@example.com>"]

[tool.poetry.dependencies]
python = "^3.8"
requests = "^2.25.1"
pandas = "^1.2.0"

[tool.poetry.dev-dependencies]
pytest = "^6.2.3"

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

依存パッケージをインストールするには、次のコマンドを使用します。

poetry install

poetryの大きな利点は、依存関係の解決が非常に高速かつ正確な点です。

また、lock fileを使用することで、再現性の高い環境を構築できます。

○サンプルコード3:flit – シンプルさを極めたツール

flitは、シンプルさを追求したパッケージングツールです。

設定ファイルを最小限に抑え、簡単にパッケージを作成できます。

flitを使用するには、まずpyproject.tomlファイルを作成します。

[build-system]
requires = ["flit_core >=3.2,<4"]
build-backend = "flit_core.buildapi"

[project]
name = "my_project"
authors = [{name = "Your Name", email = "you@example.com"}]
dynamic = ["version", "description"]

バージョンと説明は、Pythonモジュール内で指定します。

"""A short description of the project."""
__version__ = "0.1.0"

パッケージをビルドしてアップロードするには、次のコマンドを使用します。

flit build
flit publish

flitの利点は、設定が非常にシンプルで、小規模なプロジェクトや単一のPythonモジュールを公開する際に特に便利です。

○サンプルコード4:pybind11 – C++拡張の新たな王者

pybind11は、C++のコードをPythonに簡単に結合できるライブラリです。

distutilsが提供していたC拡張のビルド機能を、より現代的で使いやすい形で実現しています。

pybind11を使用したC++拡張の例を見てみましょう。

#include <pybind11/pybind11.h>

int add(int i, int j) {
    return i + j;
}

PYBIND11_MODULE(example, m) {
    m.doc() = "pybind11 example plugin";
    m.def("add", &add, "A function that adds two numbers");
}

このC++コードをPythonから呼び出すには、setup.pyファイルを次のように記述します。

from setuptools import setup, Extension
from pybind11.setup_helpers import Pybind11Extension, build_ext

ext_modules = [
    Pybind11Extension("example",
        ["example.cpp"],
    ),
]

setup(
    name="example",
    ext_modules=ext_modules,
    cmdclass={"build_ext": build_ext},
)

ビルドコマンドを実行すると、Pythonから使用可能なC++拡張モジュールが生成されます。

python setup.py build_ext --inplace

pybind11の大きな利点は、C++の最新機能を活用しつつ、Pythonとのシームレスな連携を実現できる点です。

パフォーマンスが重要な部分をC++で実装し、それ以外をPythonで書くといった柔軟な開発が可能になります。

○サンプルコード5:Cython – C言語パフォーマンスの魔法

Cythonは、PythonコードをC言語に変換することで、劇的なパフォーマンス向上を実現するツールです。

distutilsが提供していたC拡張のコンパイル機能を、より使いやすい形で提供しています。

Cythonを使用した簡単な例を見てみましょう。

まず、hello.pyxファイルを作成します。

def say_hello_to(name):
    return f"Hello, {name}!"

cpdef int fibonacci(int n):
    cdef int a = 0, b = 1
    for i in range(n):
        a, b = b, a + b
    return a

setuptoolsとCythonを使ってこのコードをコンパイルするには、setup.pyファイルを次のように記述します。

from setuptools import setup
from Cython.Build import cythonize

setup(
    name="hello_cython",
    ext_modules=cythonize("hello.pyx"),
)

ビルドコマンドを実行すると、Pythonから使用可能なC拡張モジュールが生成されます。

python setup.py build_ext --inplace

Cythonの大きな利点は、純粋なPythonコードから始めて、徐々に型情報を追加していくことで、段階的にパフォーマンスを向上させられる点です。

また、NumPyなどの科学技術計算ライブラリとの親和性が高く、数値計算を多用するプロジェクトで特に威力を発揮します。

○サンプルコード6:meson-python – ビルド速度の常識を覆す

meson-pythonは、高速なビルドシステムであるMesonをPythonプロジェクトに適用するツールです。

特に大規模なプロジェクトや、C/C++拡張を含むプロジェクトでその真価を発揮します。

meson-pythonを使用するには、まずpyproject.tomlファイルを作成します。

[build-system]
requires = ["meson-python"]
build-backend = "mesonpy"

[project]
name = "my_meson_project"
version = "0.1.0"

次に、プロジェクトのルートディレクトリにmeson.buildファイルを作成します。

project('my_meson_project', 'c', 'cpp',
  version : '0.1.0',
  default_options : ['warning_level=3'])

py_mod = import('python')
py = py_mod.find_installation()

py.install_sources(
  ['my_module.py'],
  pure : false,
  subdir : 'my_meson_project'
)

cpp_extension = py.extension_module('cpp_module',
  'cpp_module.cpp',
  install : true,
  subdir : 'my_meson_project'
)

このmeson.buildファイルは、Pythonモジュールと C++ 拡張モジュールの両方をビルドする設定を含んでいます。

プロジェクトをビルドするには、次のコマンドを実行します。

pip install .

meson-pythonの大きな利点は、ビルド速度が非常に高速な点です。

特に、大規模なプロジェクトや複雑なC/C++拡張を含むプロジェクトでその効果を実感できるでしょう。

また、Mesonの柔軟な設定システムを活用できるため、複雑なビルド要件にも対応可能です。

○サンプルコード7:scikit-build – CMakeとの完璧な融合

scikit-buildは、PythonのパッケージングシステムとCMakeビルドシステムを橋渡しするツールです。

C/C++拡張を含むプロジェクトで特に有用で、クロスプラットフォームのビルドを容易にします。

scikit-buildを使用するには、setup.pyファイルを次のように記述します。

from skbuild import setup

setup(
    name="my_scikit_build_project",
    version="0.1.0",
    packages=['my_package'],
    cmake_install_dir="my_package",
    cmake_args=['-DSOME_OPTION=ON'],
)

CMakeLists.txtファイルも作成します。

cmake_minimum_required(VERSION 3.12)
project(my_scikit_build_project)

find_package(PythonExtensions REQUIRED)

add_library(my_extension MODULE my_extension.cpp)
python_extension_module(my_extension)

install(TARGETS my_extension LIBRARY DESTINATION my_package)

プロジェクトをビルドするには、次のコマンドを実行します。

pip install .

scikit-buildの利点は、CMakeの豊富な機能をPythonパッケージングに活用できる点です。

複雑なC/C++ライブラリに依存するプロジェクトや、マルチプラットフォーム対応が必要なプロジェクトで特に威力を発揮します。

○サンプルコード8:pep517 – ビルドバックエンドの統一基準

pep517は、Pythonパッケージのビルドバックエンドを標準化するためのPEP(Python Enhancement Proposal)に基づいたツールです。

様々なビルドシステムを統一的に扱うことができ、ビルドプロセスの一貫性を保つのに役立ちます。

pep517を使用するには、まずpyproject.tomlファイルを作成します。

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

[project]
name = "my_pep517_project"
version = "0.1.0"

pep517を使ってプロジェクトをビルドするには、次のようなPythonスクリプトを作成します。

import pep517.build

pep517.build.build('.", 'wheel')

このスクリプトを実行すると、現在のディレクトリのプロジェクトからwheelファイルが生成されます。

pep517の利点は、異なるビルドバックエンド(setuptools, flit, poetryなど)を統一的に扱えることです。

プロジェクトの構成に関わらず、一貫したビルドプロセスを実現できます。

○サンプルコード9:build – PEP 517準拠の万能ツール

buildは、PEP 517に準拠したビルドフロントエンドツールです。

様々なビルドバックエンドと互換性があり、シンプルなコマンドでパッケージのビルドが可能です。

buildを使用するには、プロジェクトにpyproject.tomlファイルが必要です。

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

[project]
name = "my_build_project"
version = "0.1.0"

buildを使ってプロジェクトをビルドするには、次のコマンドを実行します。

python -m build

このコマンドは、ソース配布物(sdist)とビルド配布物(wheel)の両方を生成します。

buildの利点は、シンプルなコマンドで様々なプロジェクトをビルドできる点です。

また、PEP 517に準拠しているため、将来的な互換性も期待できます。

○サンプルコード10:hatchling – 次世代のビルドバックエンド

hatchlingは、最新のPython開発プラクティスに基づいて設計された、次世代のビルドバックエンドです。

シンプルさと柔軟性を兼ね備え、多くのプロジェクトに適用できます。

hatchlingを使用するには、pyproject.tomlファイルを次のように記述します。

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

[project]
name = "my_hatchling_project"
version = "0.1.0"
authors = [
  { name="Example Author", email="author@example.com" },
]
description = "A small example package"
readme = "README.md"
requires-python = ">=3.7"
classifiers = [
    "Programming Language :: Python :: 3",
    "License :: OSI Approved :: MIT License",
    "Operating System :: OS Independent",
]

[project.urls]
"Homepage" = "https://github.com/example/project"
"Bug Tracker" = "https://github.com/example/project/issues"

hatchlingを使ってプロジェクトをビルドするには、次のコマンドを実行します。

python -m build

hatchlingの大きな利点は、現代的なPythonプロジェクトの要求に応えつつ、シンプルな設定で始められる点です。

また、プラグインシステムを備えており、カスタマイズも容易です。

●distutils脱却のベストプラクティス

Pythonが大きく変わろうとしている今、多くの開発者がdistutilsからの移行に頭を悩ませています。

しかし、心配する必要はありません。

適切な計画と段階的なアプローチを取ることで、スムーズな移行が可能です。

ここでは、distutils脱却のベストプラクティスについて、実践的なアドバイスを交えながら解説していきます。

○レガシーコードの評価と移行計画

まず最初に行うべきは、現在のプロジェクトの状態を正確に把握することです。

レガシーコードの評価は、移行プロセス全体の基礎となる重要なステップです。

具体的には、プロジェクト内でdistutilsがどのように使用されているかを調査します。

setup.pyファイルの内容を確認し、distutilsに依存している箇所をリストアップしましょう。

例えば、次のようなコードがあれば、distutilsへの依存が確認できます。

from distutils.core import setup

setup(
    name='my_project',
    version='0.1',
    packages=['my_package'],
)

このようなコードを見つけたら、移行が必要な箇所としてマークしておきます。

また、プロジェクトで使用している外部ライブラリもチェックしましょう。

そのライブラリがdistutilsに依存していないか確認することも重要です。

評価が終わったら、移行計画を立てます。

計画には次の要素を含めると良いでしょう。

  • 移行の目標期日
  • 採用する新しいビルドシステム(例:setuptools, poetry, hatchling等)
  • 移行作業の優先順位
  • 必要なリソース(人員、時間、ツール)

移行計画を立てる際は、プロジェクトの規模や複雑さ、チームの経験レベルなどを考慮に入れることが大切です。

無理のないスケジュールを組むことで、スムーズな移行が可能になります。

○段階的アプローチ:失敗しない移行の秘訣

distutilsからの移行は、一気に行うのではなく、段階的に進めることをおすすめします。

段階的アプローチを取ることで、リスクを最小限に抑えつつ、確実に移行を進められます。

例えば、setuptoolsへの移行を考えてみましょう。

まず、setup.pyファイルの冒頭部分を変更します。

try:
    from setuptools import setup
except ImportError:
    from distutils.core import setup

setup(
    name='my_project',
    version='0.1',
    packages=['my_package'],
)

このコードは、setuptoolsが利用可能な場合はそちらを使用し、そうでない場合はdistutilsにフォールバックします。

この方法により、移行中も既存の環境との互換性を保つことができます。

次に、setup.pyファイル内のdistutils固有の機能を、setuptoolsの等価な機能に置き換えていきます。

例えば、distutils.command.build_pyモジュールを使用している場合、setuptoolsの同等の機能に置き換えます。

from setuptools.command.build_py import build_py

class CustomBuildPy(build_py):
    def run(self):
        # カスタムビルド処理
        build_py.run(self)

setup(
    # ...
    cmdclass={'build_py': CustomBuildPy},
)

このように、一つずつ機能を置き換えていくことで、問題が発生した場合も容易に原因を特定し、修正することができます。

また、移行作業中は定期的にプロジェクトのビルドとテストを行い、問題がないことを確認しましょう。

CI/CDパイプラインを活用し、自動化されたテストを実行することで、問題を早期に発見できます。

○徹底したテストと検証/安全な移行の保証

移行作業の最終段階では、徹底したテストと検証が不可欠です。

単体テスト、統合テスト、エンドツーエンドテストなど、多角的な視点からプロジェクトの動作を確認しましょう。

特に注意すべき点は、ビルドプロセスと配布物の検証です。

新しいビルドシステムで生成されたパッケージが、異なる環境で正しくインストールされ、期待通りに動作するかを確認します。

例えば、次のようなスクリプトを用意し、パッケージのインストールとインポートをテストできます。

import subprocess
import sys

def test_package_installation():
    # パッケージのインストール
    subprocess.check_call([sys.executable, "-m", "pip", "install", "."])

    # パッケージのインポート
    import my_package

    # 基本的な機能のテスト
    assert my_package.some_function() == expected_result

if __name__ == "__main__":
    test_package_installation()
    print("パッケージのインストールとインポートテストが成功しました。")

このスクリプトを異なるPythonバージョンや異なるOSで実行することで、パッケージの互換性を確認できます。

また、ドキュメントやREADMEファイルも更新することを忘れずに。

新しいビルドシステムの使用方法や、移行に伴う変更点を明確に記載しておくことで、他の開発者やユーザーの混乱を防ぐことができます。

最後に、本番環境への展開前に、ステージング環境でのテストを行うことをおすすめします。

実際の使用環境に近い条件でテストすることで、予期せぬ問題を事前に発見し、対処することができます。

●distutils廃止で直面する3大エラーと解決法

distutilsの廃止に伴い、多くの開発者が新たな課題に直面しています。

しかし、心配する必要はありません。

よくあるエラーとその解決法を知っておけば、スムーズに移行できるはずです。

ここでは、distutils廃止に伴って発生しやすい3つの主要なエラーと、その対処法について詳しく解説していきます。

○「ImportError: No module named ‘distutils’」の撃退法

最も頻繁に遭遇するエラーの一つが、「ImportError: No module named ‘distutils’」です。

このエラーは、プログラムがdistutilsモジュールをインポートしようとしたが、見つからなかった場合に発生します。

例えば、次のようなコードを実行した際にこのエラーが発生する可能性があります。

from distutils.core import setup

setup(
    name='my_project',
    version='0.1',
    packages=['my_package'],
)

このエラーを解決するには、まずsetuptoolsを使用するように変更します。

setuptoolsは、distutilsの機能を含み、さらに拡張された機能を提供するライブラリです。

次のようにコードを修正しましょう。

from setuptools import setup

setup(
    name='my_project',
    version='0.1',
    packages=['my_package'],
)

setuptoolsがインストールされていない場合は、次のコマンドでインストールできます。

pip install setuptools

このように変更することで、「ImportError: No module named ‘distutils’」エラーを解決できます。

さらに、setuptoolsを使用することで、より柔軟なパッケージング設定が可能になります。

○setuptools関連エラーを完全解決

distutilsからsetuptoolsへの移行時に、setuptools関連のエラーに遭遇することがあります。

例えば、「AttributeError: module ‘setuptools’ has no attribute ‘Extension’」というエラーがよく見られます。

このエラーは、setuptoolsの使用方法が正しくない場合に発生します。

正しい使用法は次の通りです。

from setuptools import setup, Extension

setup(
    name='my_project',
    version='0.1',
    packages=['my_package'],
    ext_modules=[Extension('module_name', ['source.c'])],
)

setuptoolsから直接Extensionクラスをインポートすることで、このエラーを回避できます。

また、「setuptools.distutils ImportError」というエラーも発生することがあります。

このエラーは、古いバージョンのsetuptoolsを使用している場合に起こりやすいです。

解決策は、setuptoolsを最新バージョンにアップデートすることです。

pip install --upgrade setuptools

このコマンドを実行することで、最新のsetuptoolsがインストールされ、多くの問題が解決されます。

○依存関係の競合/最新のトラブルシューティング

distutilsの廃止に伴い、依存関係の競合も大きな問題となっています。

特に、古いライブラリがdistutilsに依存している場合、新しい環境でエラーが発生することがあります。

例えば、次のようなエラーメッセージを見たことがありませんか?

ImportError: cannot import name 'Feature' from 'setuptools.dist'

このエラーは、setuptoolsの新しいバージョンで一部の機能が変更されたために発生します。

解決策は、プロジェクトの依存関係を最新のものに更新することです。

まず、requirements.txtファイルを作成し、プロジェクトの依存関係を記述します。

setuptools>=58.0.0
wheel>=0.37.0
# その他の依存パッケージ

そして、次のコマンドを実行して依存関係を更新します。

pip install -r requirements.txt --upgrade

また、virtualenvを使用して、プロジェクトごとに独立した環境を作成することをおすすめします。

これで、依存関係の競合を最小限に抑えることができます。

python -m venv myproject_env
source myproject_env/bin/activate  # Linuxの場合
myproject_env\Scripts\activate.bat  # Windowsの場合

さらに、pipのキャッシュをクリアすることで、古いパッケージのキャッシュによる問題を解決できることがあります。

pip cache purge

これらの方法を組み合わせることで、多くの依存関係の競合を解決できます。

しかし、すべての問題がこれで解決するわけではありません。

特に、サードパーティライブラリがdistutilsに強く依存している場合は、そのライブラリの開発者に問い合わせるか、代替のライブラリを探す必要があるかもしれません。

●distutils後の開発フロー最適化テクニック

Pythonの開発環境が大きく変わる中、私たちはより効率的な開発フローを構築する必要があります。

distutilsの廃止は、単なる一つのツールの変更ではなく、開発プロセス全体を見直す絶好の機会です。

ここでは、distutils後の時代に適した開発フロー最適化テクニックを、具体的なサンプルコードとともに紹介します。

○サンプルコード11:CIパイプラインの現代化

継続的インテグレーション(CI)は現代のソフトウェア開発には欠かせません。

distutilsの廃止を機に、CIパイプラインも最新のツールに対応させましょう。

ここでは、GitHub ActionsとPyTestを使用した現代的なCIパイプラインの例を紹介します。

まず、プロジェクトのルートディレクトリに.github/workflows/python-package.ymlファイルを作成します。

name: Python package

on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: [3.7, 3.8, 3.9, '3.10']

    steps:
    - uses: actions/checkout@v2
    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v2
      with:
        python-version: ${{ matrix.python-version }}
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install pytest
        if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
    - name: Test with pytest
      run: |
        pytest

このワークフローは、プッシュやプルリクエストのたびに自動的に実行されます。

複数のPythonバージョンでテストを行い、依存関係のインストールからテストの実行まで自動化します。

テストを書く際は、test_sample.pyのようなファイルを作成し、PyTestを使用してテストを記述します。

# test_sample.py
def test_sample():
    assert 1 + 1 == 2

def test_import():
    import your_package
    assert hasattr(your_package, 'some_function')

このようなCIパイプラインを導入することで、コードの品質を常に高い水準に保ちつつ、新しいビルドシステムへの移行も安全に行えます。

○サンプルコード12:自動ドキュメント生成の極意

ドキュメンテーションは、プロジェクトの重要な一部です。

特に、distutilsからの移行期には、新しいビルドシステムの使用方法を明確に記述することが重要です。

ここでは、Sphinxを使用した自動ドキュメント生成の方法を紹介します。

まず、Sphinxをインストールし、プロジェクトのドキュメンテーションを初期化します。

pip install sphinx
sphinx-quickstart docs

次に、conf.pyファイルを編集して、自動APIドキュメント生成を設定します。

# conf.py
import os
import sys
sys.path.insert(0, os.path.abspath('..'))

extensions = [
    'sphinx.ext.autodoc',
    'sphinx.ext.napoleon',
]

# その他の設定...

そして、ドキュメントのソースファイル(例:api.rst)を作成します。

API Reference
=============

.. automodule:: your_package
   :members:
   :undoc-members:
   :show-inheritance:

最後に、ドキュメントをビルドします。

cd docs
make html

このプロセスをpython-package.ymlに組み込むことで、コードの変更に合わせて自動的にドキュメントを更新できます。

- name: Build documentation
  run: |
    pip install sphinx
    cd docs
    make html

自動生成されたドキュメントは、新しいビルドシステムの使用方法や、プロジェクトの構造変更を開発者やユーザーに明確に伝える役割を果たします。

○サンプルコード13:コミュニティリソースの活用術

distutilsの廃止に伴う移行作業でも、コミュニティのリソースを効果的に利用することで、多くの問題を解決できます。

例えば、GitHubのIssueテンプレートを使って、コミュニティからのフィードバックを効率的に収集できます。

.github/ISSUE_TEMPLATE/bug_report.mdファイルを作成し、次のような内容を記述します。

---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
A clear and concise description of what you expected to happen.

**Environment (please complete the following information):**
 - OS: [e.g. Ubuntu 20.04]
 - Python version: [e.g. 3.8.5]
 - Package version: [e.g. 1.0.0]

**Additional context**
Add any other context about the problem here.

このテンプレートを使用することで、バグレポートに必要な情報を漏れなく収集でき、問題解決のスピードが格段に上がります。

また、コミュニティとの対話を促進するために、READMEファイルに貢献ガイドラインへのリンクを追加するのも効果的です。

# Your Project Name

## Contributing

We welcome contributions! Please see our [Contributing Guidelines](CONTRIBUTING.md) for more details.

## Code of Conduct

This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code.

コミュニティリソースを効果的に活用することで、distutilsからの移行に関する知見を共有し、新しいビルドシステムの採用をスムーズに進めることができます。

まとめ

distutilsの廃止は、多くの開発者にとって大きな変化をもたらしましたが、同時に新たな可能性も開いてくれました。

私たちはこの変化を恐れるのではなく、むしろチャンスとして捉えるべきだと考えます。

本記事で紹介した10個の代替手段は、それぞれに特徴があり、プロジェクトの規模や要件に応じて選択できます。

distutilsからの移行は、単なるツールの置き換えではありません。

開発プロセス全体を見直し、最適化する絶好の機会です。

レガシーコードの評価から始まり、段階的なアプローチを取ることで、安全に移行を進められます。

また、徹底したテストと検証を行うことで、品質を保証しながら新しいシステムへ移行できます。