python-project-structure について
新規・既存の Python プロジェクトを整理する開発者向けのガイドです。モジュール境界、公開 API、ディレクトリ構成、インポート、テスト配置を扱います。
主な機能
- 01モジュールの凝集性と境界
- 02__all__ による公開 API の明示
- 03フラット型とドメイン型の構成
- 04テスト配置の方針
- 05命名とインポートの規約
活用シーン
- 01新しい Python プロジェクトの設計
- 02既存コードベースの再構成
- 03再利用可能な Python パッケージの作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ wshobson/ agents --skill python-project-structureインストール後、Claude Code で/python-project-structureを入力して読み込まれたか確認します。
詳細
Python プロジェクトの構造とモジュールアーキテクチャ
明確なモジュール境界、明示的な公開インターフェース、保守しやすいディレクトリ構造を備えた、よく整理された Python プロジェクトを設計します。適切な構成により、コードは見つけやすくなり、変更は予測しやすくなります。
このスキルを使用する場面
- 新しい Python プロジェクトをゼロから始めるとき
- 既存のコードベースを明確にするために再編成するとき
__all__を使ってモジュールの公開 API を定義するとき- フラットなディレクトリ構造とネストしたディレクトリ構造のどちらにするか決めるとき
- テストファイルの配置戦略を決定するとき
- 再利用可能なライブラリパッケージを作成するとき
中心となる概念
1. モジュールの凝集性
一緒に変更される関連コードをグループ化します。モジュールは単一の明確な目的を持つべきです。
2. 明示的なインターフェース
__all__ を使って公開するものを定義します。そこに記載されていないものはすべて内部実装の詳細です。
3. フラットな階層
浅いディレクトリ構造を優先します。本当に必要なサブドメインにのみ深さを追加します。
4. 一貫した規約
命名と構成のパターンをプロジェクト全体で一律に適用します。
クイックスタート
myproject/
├── src/
│ └── myproject/
│ ├── __init__.py
│ ├── services/
│ ├── models/
│ └── api/
├── tests/
├── pyproject.toml
└── README.md
基本的なパターン
パターン 1: 1 ファイルにつき 1 つの概念
各ファイルは、単一の概念または密接に関連する関数のセットに焦点を当てるべきです。次のような場合は分割を検討してください:
- 無関係な複数の責務を処理している
- 300〜500 行を超えて大きくなっている(複雑さによって異なります)
- 異なる理由で変更されるクラスを含んでいる
# Good: Focused files
# user_service.py - User business logic
# user_repository.py - User data access
# user_models.py - User data structures
# Avoid: Kitchen sink files
# user.py - Contains service, repository, models, utilities...
パターン 2: __all__ による明示的な公開 API
すべてのモジュールの公開インターフェースを定義します。記載されていないメンバーは内部実装の詳細です。
# mypackage/services/__init__.py
from .user_service import UserService
from .order_service import OrderService
from .exceptions import ServiceError, ValidationError
__all__ = [
"UserService",
"OrderService",
"ServiceError",
"ValidationError",
]
# Internal helpers remain private by omission
# from .internal_helpers import _validate_input # Not exported
パターン 3: フラットなディレクトリ構造
ネストは最小限に抑えます。深い階層はインポートを冗長にし、ナビゲーションを困難にします。
# Preferred: Flat structure
project/
├── api/
│ ├── routes.py
│ └── middleware.py
├── services/
│ ├── user_service.py
│ └── order_service.py
├── models/
│ ├── user.py
│ └── order.py
└── utils/
└── validation.py
# Avoid: Deep nesting
project/core/internal/services/impl/user/
分離が必要な本当のサブドメインが存在する場合にのみ、サブパッケージを追加します。
パターン 4: テストファイルの構成
1 つのアプローチを選び、プロジェクト全体で一貫して適用します。
オプション A: コードと同じ場所に置くテスト
src/
├── user_service.py
├── test_user_service.py
├── order_service.py
└── test_order_service.py
利点: テストは、検証対象のコードの隣に置かれます。カバレッジの不足を簡単に確認できます。
オプション B: 並列のテストディレクトリ
src/
├── services/
│ ├── user_service.py
│ └── order_service.py
tests/
├── services/
│ ├── test_user_service.py
│ └── test_order_service.py
利点: 本番コードとテストコードが明確に分離されます。大規模なプロジェクトで標準的な方法です。
応用的なパターン
パターン 5: パッケージの初期化
__init__.py を使って、パッケージの利用者にクリーンな公開インターフェースを提供します。
# mypackage/__init__.py
"""MyPackage - A library for doing useful things."""
from .core import MainClass, HelperClass
from .exceptions import PackageError, ConfigError
from .config import Settings
__all__ = [
"MainClass",
"HelperClass",
"PackageError",
"ConfigError",
"Settings",
]
__version__ = "1.0.0"
利用者はパッケージから直接インポートできるようになります:
from mypackage import MainClass, Settings
パターン 6: レイヤードアーキテクチャ
関心事を明確に分離するために、アーキテクチャのレイヤーごとにコードを構成します。
myapp/
├── api/ # HTTP handlers, request/response
│ ├── routes/
│ └── middleware/
├── services/ # Business logic
├── repositories/ # Data access
├── models/ # Domain entities
├── schemas/ # API schemas (Pydantic)
└── config/ # Configuration
各レイヤーは、その下のレイヤーにのみ依存し、上のレイヤーには決して依存しないようにします。
パターン 7: ドメイン駆動の構造
複雑なアプリケーションでは、技術的なレイヤーではなくビジネスドメインごとに構成します。
ecommerce/
├── users/
│ ├── models.py
│ ├── services.py
│ ├── repository.py
│ └── api.py
├── orders/
│ ├── models.py
│ ├── services.py
│ ├── repository.py
│ └── api.py
└── shared/
├── database.py
└── exceptions.py
ファイルとモジュールの命名
規約
- すべてのファイル名とモジュール名に
snake_caseを使用します:user_repository.py - 意味を曖昧にする略語は避けます:
usr_repo.pyではなくuser_repository.py - クラス名をファイル名に一致させます:
user_service.py内のUserService
インポートスタイル
明確さと信頼性のために絶対インポートを使用します:
# Preferred: Absolute imports
from myproject.services import UserService
from myproject.models import User
# Avoid: Relative imports
from ..services import UserService
from . import models
相対インポートは、モジュールが移動または再編成されると壊れる可能性があります。
ベストプラクティスのまとめ
- ファイルを焦点を絞った状態に保つ - 1 ファイルにつき 1 つの概念、300〜500 行で分割を検討します(複雑さによって異なります)
__all__を明示的に定義する - 公開インターフェースを明確にします- フラットな構造を優先する - 本当のサブドメインにのみ深さを追加します
- 絶対インポートを使用する - より信頼性が高く、明確です
- 一貫性を保つ - パターンをプロジェクト全体で一律に適用します
- 名前を内容に一致させる - ファイル名はその目的を表すべきです
- 関心事を分離する - レイヤーを明確に保ち、依存関係を一方向に流します
- 構造を文書化する - 構成を説明する README を含めます