Pythonパッケージの作成: 開発からPyPIへの公開ガイド
コードからPyPIへのデプロイまで、Pythonパッケージングをマスターしましょう。
Python パッケージング は大幅に進化し、現代のツールと標準により、コードの配布がこれまで以上に簡単になりました。
このガイドでは、プロフェッショナルな Python パッケージの作成と PyPI への公開方法について説明します。Python に初めて触れる方や、クイックリファレンスが必要な場合は、Python クイックリファレンス を確認して、Python の基本を素早く理解してください。

なぜ Python のコードをパッケージ化するのか?
Python プロジェクトをパッケージ化することには、いくつかの利点があります:
- 再利用性: 複数のプロジェクト間でコードをコピー&ペーストすることなく共有できます
- 配布:
pip installで簡単に他の人にコードをインストールさせられます - 依存関係管理: 依存関係を明確に指定して管理できます
- バージョニング: リリースをトラックし、後方互換性を維持できます
- プロフェッショナルな基準: Python コミュニティのベストプラクティスに従います
- ドキュメント: ドキュメント作成とテストを促進する構造になります
現代的な Python パッケージ構造
よく整理されたパッケージは次の構造を採用します:
my-package/
├── src/
│ └── mypackage/
│ ├── __init__.py
│ ├── core.py
│ └── utils.py
├── tests/
│ ├── __init__.py
│ └── test_core.py
├── docs/
│ └── index.md
├── .github/
│ └── workflows/
│ └── publish.yml
├── pyproject.toml
├── README.md
├── LICENSE
└── .gitignore
src-layout はフラット構造よりも現在推奨されています。その理由は以下の通りです:
- 開発中にインストールされていないコードを誤ってインポートするのを防ぎます
- インストールを強制してテストをより信頼性高くします
- ソースコードを他のプロジェクトファイルから明確に分離します
パッケージの内部構造を整理する際には、コードの保守性とテスト性を高めるためにクリーンアーキテクチャの原則を適用することを検討してください。Python のクリーンアーキテクチャ向け設計パターン では、SOLID 原則、依存性注入、およびレイヤードアーキテクチャパターンについて説明しています。
pyproject.toml ファイル: 現代的な設定
pyproject.toml (PEP 518, 621) は、setup.py に代わる Python プロジェクト設定の現代的な標準です:
[build-system]
requires = ["setuptools>=68.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "mypackage"
version = "0.1.0"
description = "A fantastic Python package"
readme = "README.md"
requires-python = ">=3.8"
license = {text = "MIT"}
authors = [
{name = "Your Name", email = "you@example.com"}
]
keywords = ["example", "tutorial", "package"]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
dependencies = [
"requests>=2.28.0",
"click>=8.1.0",
]
[project.optional-dependencies]
dev = [
"pytest>=7.4.0",
"black>=23.0.0",
"flake8>=6.0.0",
"mypy>=1.5.0",
]
docs = [
"sphinx>=7.0.0",
"sphinx-rtd-theme>=1.3.0",
]
[project.urls]
Homepage = "https://github.com/yourusername/mypackage"
Documentation = "https://mypackage.readthedocs.io"
Repository = "https://github.com/yourusername/mypackage"
Issues = "https://github.com/yourusername/mypackage/issues"
[project.scripts]
mypackage-cli = "mypackage.cli:main"
[tool.setuptools.packages.find]
where = ["src"]
主な設定セクション
- build-system: ビルドバックエンド(setuptools、hatchling、poetry-core、flit-core)を指定します
- project: コアメタデータと依存関係
- project.optional-dependencies: エクストラ機能の依存関係(dev、docs、テスト)
- project.scripts: コマンドラインエントリポイント
- tool.*: ツール固有の設定(black、pytest、mypy など)
ビルドバックエンドの選択
Setuptools(標準的な選択)
最も広く使用されており、互換性が良いオプションです:
[build-system]
requires = ["setuptools>=68.0", "wheel"]
build-backend = "setuptools.build_meta"
利点: 普遍的な互換性、豊富な機能、大規模なエコシステム
欠点: 新しい代替手段に比べて設定が冗長で、速度が遅い
Hatchling(現代的で高速)
軽量でパフォーマンスが良い現代的なバックエンドです:
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
利点: 高速なビルド、シンプルな設定、デフォルトが良い
欠点: setuptools よりもプラグインが少ない
Poetry(オールインワン)
依存関係と環境管理を完全に統合します:
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
[tool.poetry]
name = "mypackage"
version = "0.1.0"
description = "A fantastic Python package"
authors = ["Your Name <you@example.com>"]
[tool.poetry.dependencies]
python = "^3.8"
requests = "^2.28.0"
利点: 依存関係解決、ロックファイル、統合ワークフロー
欠点: 仕事フローが異なる、ツールの表面積が大きい
Flit(ミニマル)
シンプルなパッケージに最適なツールです:
[build-system]
requires = ["flit_core >=3.2,<4"]
build-backend = "flit_core.buildapi"
利点: 非常にシンプル、設定が最小限
欠点: 複雑なパッケージには機能が限られている
パッケージのビルド
ビルドツールのインストール
# モダンなビルドツールをインストール
pip install build
# Poetry を使用する場合
pip install poetry
# Hatchling を使用する場合
pip install hatch
ディストリビューションファイルのビルド
build パッケージを使用(任意のバックエンドと互換性があります):
# 以前のビルドをクリーンアップ
rm -rf dist/ build/ *.egg-info
# ソースディストリビューションと wheel をビルド
python -m build
# これにより生成されるファイル:
# dist/mypackage-0.1.0.tar.gz (ソースディストリビューション)
# dist/mypackage-0.1.0-py3-none-any.whl (wheel)
Poetry を使用する場合:
poetry build
Hatch を使用する場合:
hatch build
ディストリビューション形式の理解
ソースディストリビューション (sdist) - .tar.gz
- ソースコードとビルド指示を含みます
- ユーザーの pip がインストール時にビルドします
- テスト、ドキュメント、その他の開発ファイルも含まれます
Wheel - .whl
- 事前にビルドされたバイナリディストリビューション
- インストールが迅速(ビルドステップ不要)
- プラットフォーム固有または純粋な Python
- ディストリビューションに推奨される形式
PyPI への公開
方法1: Twine を使用した手動アップロード(伝統的)
# Twine をインストール
pip install twine
# アップロード前にパッケージを確認
twine check dist/*
# まず TestPyPI にアップロードすることを推奨
twine upload --repository testpypi dist/*
# TestPyPI からインストールをテスト
pip install --index-url https://test.pypi.org/simple/ mypackage
# 本番 PyPI にアップロード
twine upload dist/*
~/.pypirc に資格情報を設定します:
[distutils]
index-servers =
pypi
testpypi
[pypi]
username = __token__
password = pypi-AgEIcHlwaS5vcmc...
[testpypi]
repository = https://test.pypi.org/legacy/
username = __token__
password = pypi-AgENdGVzdC5weXBpLm9yZw...
方法2: 信頼された公開(CI/CD で推奨)
信頼された公開は、CI/CD プラットフォームからトークンを保存せずに OpenID Connect (OIDC) を使用して認証します。
PyPI での設定:
- PyPI プロジェクト設定にアクセス
- 「公開」セクションに移動
- 新しい「pending publisher」を追加
- 次のように設定:
- 所有者: あなたの GitHub ユーザー名/組織
- リポジトリ: リポジトリ名
- ワークフロー:
publish.yml - 環境:
release(オプションですが推奨)
GitHub Actions ワークフロー (.github/workflows/publish.yml):
name: Publish to PyPI
on:
release:
types: [published]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install build dependencies
run: |
python -m pip install --upgrade pip
pip install build
- name: Build package
run: python -m build
- name: Store distribution packages
uses: actions/upload-artifact@v3
with:
name: python-package-distributions
path: dist/
publish:
needs: build
runs-on: ubuntu-latest
environment: release
permissions:
id-token: write
steps:
- name: Download distributions
uses: actions/download-artifact@v3
with:
name: python-package-distributions
path: dist/
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
利点:
- 管理またはセキュリティ対策が必要な API トークンがありません
- OIDC による自動認証
- 環境保護ルールを通じたセキュリティの向上
- 公開履歴のトレーサビリティ
ベストプラクティス
1. バージョン管理
セマンティックバージョニング (SemVer) を使用: MAJOR.MINOR.PATCH
# バージョンアップツールをインストール
pip install bump2version
# バージョンを上げる
bump2version patch # 0.1.0 -> 0.1.1
bump2version minor # 0.1.1 -> 0.2.0
bump2version major # 0.2.0 -> 1.0.0
.bumpversion.cfg で設定:
[bumpversion]
current_version = 0.1.0
commit = True
tag = True
[bumpversion:file:pyproject.toml]
search = version = "{current_version}"
replace = version = "{new_version}"
[bumpversion:file:src/mypackage/__init__.py]
search = __version__ = "{current_version}"
replace = __version__ = "{new_version}"
2. 必要なファイルの含まれる
README.md: 明確なプロジェクト説明、インストール、使用例
LICENSE: 適切なライセンスを選択(MIT、Apache 2.0、GPL など)
CHANGELOG.md: バージョン間の変更を記録
.gitignore: ビルドアーティファクト、キャッシュ、仮想環境を除外
3. 継続的なテスト
# テスト依存関係をインストール
pip install pytest pytest-cov
# テストを実行してカバレッジを取得
pytest --cov=mypackage tests/
# カバレッジレポートを生成
pytest --cov=mypackage --cov-report=html tests/
pyproject.toml で設定:
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
python_functions = ["test_*"]
addopts = "--strict-markers --cov=mypackage"
4. コード品質ツール
# フォーマット
black src/ tests/
# リント
flake8 src/ tests/
# 型チェック
mypy src/
# インポートの並べ替え
isort src/ tests/
pre-commit ハックに統合(.pre-commit-config.yaml):
repos:
- repo: https://github.com/psf/black
rev: 23.9.1
hooks:
- id: black
- repo: https://github.com/pycqa/flake8
rev: 6.1.0
hooks:
- id: flake8
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.5.1
hooks:
- id: mypy
5. ドキュメンテーション
Sphinx を使用してドキュメンテーションを作成します:
# Sphinx をインストール
pip install sphinx sphinx-rtd-theme
# ドキュメンテーションを初期化
cd docs
sphinx-quickstart
# ドキュメンテーションをビルド
make html
または、Markdown ベースのドキュメンテーションのために MkDocs を使用します:
pip install mkdocs mkdocs-material
mkdocs new .
mkdocs serve
6. 連続インテグレーション
Python パッケージをさまざまなプラットフォームや環境でテストすることは、信頼性にとって重要です。Python のパフォーマンスが異なるデプロイシナリオにおける詳細については、AWS Lambda のパフォーマンス: JavaScript vs Python vs Golang を参照してください。この記事では、Python がサーバーレス環境でどのようにパフォーマンスを発揮するかを探索しています。
完全な CI/CD ワークフロー (.github/workflows/ci.yml):
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
- name: Run tests
run: pytest --cov=mypackage --cov-report=xml
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
file: ./coverage.xml
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install black flake8 mypy
- name: Black formatting check
run: black --check src/ tests/
- name: Flake8
run: flake8 src/ tests/
- name: MyPy
run: mypy src/
一般的な問題とその解決策
問題1: インストール後のインポートエラー
問題: パッケージはインストールされているが、インポートに失敗します
解決策: __init__.py ファイルと正しい pyproject.toml 設定を使用して、適切なパッケージ構造を保証してください:
[tool.setuptools.packages.find]
where = ["src"]
include = ["mypackage*"]
問題2: 依存関係が不足している
問題: パッケージはインストールされるが、実行時に必要な依存関係が不足しています
解決策: すべてのランタイム依存関係を pyproject.toml に宣言してください:
[project]
dependencies = [
"requests>=2.28.0",
"click>=8.1.0",
]
問題3: バージョンの競合
問題: パッケージは開発環境では動作するが、本番環境では失敗します
解決策: バーチャル環境を使用し、最小バージョンを指定してください:
# イソレーションされた環境を作成
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# 開発用に編集可能なモードでインストール
pip install -e ".[dev]"
問題4: パッケージサイズが大きい
問題: パッケージのダウンロード/インストールに時間がかかりすぎる
解決策: 不要なファイルを MANIFEST.in で除外してください:
include README.md
include LICENSE
include pyproject.toml
recursive-include src *.py
recursive-exclude * __pycache__
recursive-exclude * *.py[co]
recursive-exclude tests *
recursive-exclude docs *
問題5: プラットフォーム固有の問題
問題: パッケージは1つのOSでは動作するが、他のOSでは失敗します
解決策: CI/CD マトリクスビルドを使用して、複数のプラットフォームでテストしてください(上記の CI 例を参照)
公開チェックリスト
パッケージを PyPI に公開する前に確認してください:
- すべての Python バージョンでテストが成功している
- コードはフォーマットされ、リントされている
- README.md は例を含めて完成している
- LICENSE ファイルが含まれている
- バージョン番号が更新されている
- CHANGELOG.md が更新されている
- 依存関係が正しく指定されている
- パッケージがエラーなくビルドされている (
python -m build) - TestPyPI でパッケージがテストされている
- ドキュメンテーションが最新になっている
- Git リポジトリがバージョンタグでマークされている
- GitHub リリースが作成されている(信頼された公開用)
高度なトピック
エントリポイントと CLI ツール
コマンドラインインターフェースを作成します:
[project.scripts]
mypackage = "mypackage.cli:main"
src/mypackage/cli.py での実装:
import click
@click.command()
@click.option('--name', default='World', help='Greet this name')
def main(name):
"""Simple CLI tool example"""
click.echo(f'Hello, {name}!')
if __name__ == '__main__':
main()
Python パッケージが外部 API と相互作用する現実の例については、Ollama と Python の統合 を参照してください。
プラグインシステム
プラグインの検出を有効にします:
[project.entry-points."mypackage.plugins"]
plugin_a = "mypackage_plugin_a:PluginA"
C 拡張
パフォーマンスが重要なコードに使用します:
[tool.setuptools.ext-modules]
name = "mypackage._speedups"
sources = ["src/mypackage/_speedups.c"]
ネームスペースパッケージ
共通ネームスペースの下で配布されるパッケージに使用します:
[tool.setuptools.packages.find]
where = ["src"]
include = ["company.*"]
[tool.setuptools.package-data]
"company.mypackage" = ["py.typed"]
有用なツールとリソース
パッケージ開発ツール
- cookiecutter: Python パッケージ用のプロジェクトテンプレート
- tox: Python バージョンにわたるテスト自動化
- nox: トックスの代替として柔軟なテスト自動化
- pre-commit: コード品質用の Git ハックフレームワーク
- commitizen: コミットメッセージとバージョニングの標準化
ドキュメンテーションプラットフォーム
- Read the Docs: 無料のドキュメンテーションホスティング
- GitHub Pages: MkDocs や Sphinx ドキュメンテーションをホスティング
- pdoc: シンプルな API ドキュメンテーション生成器
パッケージリポジトリ
- PyPI: 公式 Python パッケージインデックス (pypi.org)
- TestPyPI: テスト環境 (test.pypi.org)
- Anaconda.org: Conda パッケージ配布
- GitHub Packages: プライベートパッケージホスティング
モニタリングと分析
- PyPI Stats: パッケージのダウンロード統計
- Libraries.io: 依存関係のモニタリングとアラート
- Snyk: セキュリティ脆弱性スキャン
- Dependabot: 依存関係の自動更新
結論
現代的な Python パッケージングは、pyproject.toml や強力なビルドバックエンド、セキュアな信頼された公開など、開発者フレンドリーな標準に進化しています。このガイドに従うことで、ユーザーに効果的にサービスするプロフェッショナルで保守可能な Python パッケージを作成できます。
主要なポイント:
- 新しいプロジェクトでは pyproject.toml を使用してください
- ご自身のニーズに合った正しい ビルドバックエンド を選択してください
- 自動テスト と CI/CD を実装してください
- セキュアでトークンフリーのデプロイに 信頼された公開 を使用してください
- セマンティックバージョニング を実行し、変更履歴を維持してください
- 総合的な ドキュメンテーション と例を提供してください
Python パッケージングエコシステムは、ツール、標準、セキュリティ機能が改善され続けています。Python 拡張提案(PEPs)やコミュニティのベストプラクティスを常に更新して、パッケージを現代的で保守可能な状態に保つようにしてください。
有用なリンク
- Python パッケージングユーザーガイド
- PEP 518 - ビルドシステム要件の指定
- PEP 621 - pyproject.toml にプロジェクトメタデータを保存する
- PyPI 信頼された公開ドキュメンテーション
- Setuptools ドキュメンテーション
- Poetry ドキュメンテーション
- Hatch ドキュメンテーション
- TestPyPI
- Python Packaging Authority GitHub
- セマンティックバージョニング
- ライセンスの選択