Pythonでパッケージを開発したり、GitHubなどからダウンロードしたソースコードをインストールしたりする際、かつてはpython setup.py installというコマンドが標準的に使われてきました。

しかし、現在のPythonパッケージングのエコシステムにおいて、この手法はすでに非推奨 (Deprecated)とされており、直接実行することは推奨されていません。

この記事では、setup.pyを用いたインストールの仕組みを振り返りつつ、なぜ非推奨となったのか、そして現在の標準であるpippyproject.tomlを用いた新しいインストール手順について、技術的な背景を交えて詳しく解説します。

最新のベストプラクティスを理解し、安全でメンテナンス性の高い開発環境を構築しましょう。

python setup.py installとは何か

Pythonにおけるsetup.pyは、パッケージのメタデータ(名称、バージョン、依存関係など)を定義し、ビルドやインストールを制御するためのスクリプトファイルです。

長年、Pythonの標準ライブラリであったdistutilsや、その機能を拡張したsetuptoolsを利用して記述されてきました。

コマンドの役割と仕組み

python setup.py installを実行すると、Pythonインタープリタは以下のプロセスを順次実行します。

  1. ビルド処理:ソースコードをコンパイルし、実行可能な形式にまとめます。
  2. メタデータの生成:パッケージ情報を.egg-infoディレクトリに書き出します。
  3. ファイルのコピー:ビルドされたファイルをPythonのsite-packagesディレクトリに配置します。

このコマンドは、インターネットを介さずにローカルにあるソースコードから直接環境に反映させる手段として重宝されてきました。

しかし、この手法にはアンインストールが困難であることや、依存関係の解決が不十分であるといった構造的な課題が残されていました。

distutilsとsetuptoolsの関係

古くはPython標準のdistutilsが担っていた役割ですが、機能不足を補うために登場したのがsetuptoolsです。

現代のsetup.pyは、ほぼ例外なくsetuptoolsをインポートして記述されます。

しかし、後述するPEP (Python Enhancement Proposals) の進化により、これらのツールを直接ユーザーが叩く時代は終わりを迎えました。

なぜ非推奨になったのか:その背景と理由

現在、setup.pyを直接実行すると、環境によっては警告が表示されるか、あるいは正常に動作しない場合があります。

これには明確な技術的理由があります。

PEP 517とPEP 518による変革

かつてのPythonパッケージングは、ビルドツールとしてsetuptoolsがインストールされていることを前提としていました。

しかし、これではsetuptools以外のモダンなビルドツール (Poetry, Flit, Hatchなど) を利用することが困難でした。

これを解決するために策定されたのが、PEP 517 (A build-backend interface)PEP 518 (Specifying build requirements) です。

これにより、ビルドに必要なツールをpyproject.tomlというファイルで定義し、インストーラ (pipなど) が自動的にビルド環境を構築する仕組みが整いました。

setup.py installの欠点

直接インストールを行う従来の手法には、以下のようなリスクとデメリットが存在します。

項目内容
アンインストールの欠如setup.py installで入れたものは、手動でファイルを消さない限り完全に削除できません。
依存関係の不整合依存ライブラリのバージョン競合が発生した際、適切に解決されないことがあります。
Wheel形式の未利用現代の標準配布形式であるWheel (バイナリ配布) を介さないため、インストール速度が遅く、環境再現性が低くなります。
ビルド分離の欠如現在の環境にインストールされているライブラリがビルドプロセスに干渉し、予期せぬ挙動を引き起こす可能性があります。

これらの問題を解決するため、Pythonコア開発チームおよびPyPA (Python Packaging Authority) は、直接的なsetup.pyの実行を避け、pipをフロントエンドとして利用することを強く推奨しています。

pipでの代替手順:正しいインストール方法

では、現在推奨されている方法でローカルパッケージをインストールするにはどうすればよいのでしょうか。

その答えは、フロントエンドツールであるpipを利用することです。

pip install . を使う

カレントディレクトリにsetup.pypyproject.tomlが存在する場合、以下のコマンドを実行します。

Shell
# カレントディレクトリのパッケージをインストール
pip install .

このコマンドは、内部的に一時的な仮想環境を作成してビルドを行い、適切なメタデータを生成した上でインストールを実行します。

これにより、pip uninstallによる削除も可能になります。

編集可能モード (Editable Mode)

開発中のパッケージをインストールする場合、コードを変更するたびに再インストールするのは非効率です。

その場合は、編集可能モード (-e オプション)を利用します。

Shell
# ソースコードの変更が即座に反映されるモードでインストール
pip install -e .

これにより、site-packagesには実際のファイルではなく、ソースディレクトリへのシンボリックリンク(あるいは.pthファイル)が配置されます。

開発者はソースを編集するだけで、インストール済みのパッケージとしてその変更をテストできます。

pyproject.tomlへの移行

現代のPythonプロジェクトにおいて、setup.pyは必須ではありません。

むしろ、pyproject.tomlに移行することが強く推奨されています。

pyproject.tomlの基本構造

pyproject.tomlは、ビルドシステムの設定とプロジェクトのメタデータを一括管理するための設定ファイルです。

以下に、setuptoolsをバックエンドとして使用する場合の標準的な構成例を示します。

TOML
[build-system]
# ビルドに必要なツールを指定(PEP 518)
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"

[project]
# プロジェクトのメタデータ(PEP 621)
name = "my_awesome_package"
version = "0.1.0"
description = "最新のパッケージング規格に準拠したサンプル"
readme = "README.md"
requires-python = ">=3.8"
dependencies = [
    "requests>=2.25.1",
    "numpy>=1.20.0"
]

[project.scripts]
# コマンドラインツールの登録
my-command = "my_package.main:main"

このファイルを用意することで、setup.pyを記述することなく、pip install .によるインストールが可能になります。

setup.cfgとの併用

もし、複雑なビルド設定が必要でpyproject.tomlだけでは記述が困難な場合は、設定をsetup.cfgに切り出し、setup.pyは最小限の記述(あるいはファイル自体の削除)に留めるのが中期的には一般的な構成でした。

しかし、現在ではPEP 621によりメタデータもpyproject.tomlに集約できるようになっています。

実践:パッケージの作成とインストール例

実際に、簡単なパッケージ構成を作成し、推奨される方法でインストールする流れを確認してみましょう。

1. ディレクトリ構成の作成

以下のようなディレクトリ構造を作成します。

my_project/
├── pyproject.toml
├── src/
│   └── my_package/
│       ├── __init__.py
│       └── core.py
└── tests/
    └── test_core.py

2. ソースコードの記述

src/my_package/core.pyに簡単な関数を記述します。

Python
# src/my_package/core.py

def greet(name):
    """
    指定された名前に挨拶を返す関数
    """
    return f"Hello, {name}! Welcome to modern Python packaging."

if __name__ == "__main__":
    # 直接実行時の動作
    print(greet("Developer"))

3. インストールの実行

プロジェクトのルートディレクトリ(pyproject.tomlがある場所)で、pipを使用してインストールします。

ここでは開発を想定して-eオプションを使用します。

Shell
# 編集可能モードでインストールを実行
pip install -e .
実行結果
Obtaining file:///path/to/my_project
  Installing build dependencies ... done
  Checking if build backend supports build_editable ... done
  Getting requirements to build editable ... done
  Preparing editable metadata (pyproject.toml) ... done
Installing collected packages: my_awesome_package
Successfully installed my_awesome_package-0.1.0

4. 動作確認

インストールされたパッケージがどこからでも呼び出せるか確認します。

Python
# 別の場所からPythonを起動して実行
import my_package.core
print(my_package.core.greet("World"))
実行結果
Hello, World! Welcome to modern Python packaging.

このように、setup.py installを直接叩かなくても、pipを通じて安全かつスマートにインストールが完了します。

よくある質問とトラブルシューティング

移行期において、いくつかの疑問が生じることがあります。

代表的なケースとその対処法をまとめました。

古いプロジェクトにsetup.pyしかありません。どうすれば良いですか?

python setup.py installを直接実行するのではなく、pip install .を実行してください。

pipはsetup.pyを自動的に検出して適切にラップして処理します。

依存関係を手動で解決したい場合は?

setup.py installは依存関係を無視して無理やりインストールするオプションなどがあり環境を壊す原因になります。

依存関係に問題がある場合はrequirements.txtを適切に管理するか、どうしても必要ならpip install –no-deps .のようにpipのオプションを利用してください(ただし推奨はされません)。

「Easy Install」や「Egg」という言葉を見かけますが?

これらは古いPythonパッケージングの仕組みです。

かつてsetup.py installは内部でeasy_installを呼ぶことがありましたが、現在はWheel形式が標準です。

Egg形式は過去の遺物と考え、可能な限りWheel形式で配布・利用することを推奨します。

注意点:セキュリティと環境分離

パッケージをインストールする際は、常に以下の点に注意してください。

仮想環境の利用

システム標準のPython環境に直接インストールすることは避けてください。

venvやcondaを利用して、プロジェクトごとに独立した環境を作成しましょう。

信頼できないソースの実行

setup.pyは任意のPythonコードを実行できるため、悪意のあるスクリプトが含まれている可能性があります。

中身を確認できない、あるいは信頼できないリポジトリでinstallを実行するのは危険です。

ビルド済みバイナリの活用

C拡張などを含むパッケージの場合、ソースからビルドするとコンパイラの設定で躓くことが多いです。

可能な限りPyPIから提供されているWheel(ビルド済みバイナリ)をpip installで利用するようにしましょう。

まとめ

本記事では、python setup.py installの歴史的な役割から、非推奨となった背景、そして現代の標準的な代替手法までを詳しく解説しました。

かつては当たり前だったsetup.pyの直接実行は、現在では不完全なインストールや環境の汚染を招くリスクを孕んでいます。

これからのPython開発においては、以下の3点を徹底することが重要です。

  • インストールのフロントエンドには必ず「pip」を使用する。
  • 新しいプロジェクトでは「pyproject.toml」による構成を採用する。
  • 開発時は「pip install -e .」を活用して効率化を図る。

Pythonのパッケージングエコシステムは進化し続けています。

古い情報を鵜呑みにせず、最新のPEPに基づいた標準的な手法を選択することで、堅牢で再現性の高い開発環境を維持していきましょう。