1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Python】Python プロジェクト構成のベストプラクティス徹底ガイド

Posted at

はじめに

── 新規プロジェクトは「src レイアウト」だけ覚えておけば勝てる。

Python でプロジェクトを始めるとき、
「どこに何を置けばいいの?」「tests は分ける?」「pyproject.toml は?」
……と迷子になりがちです。

でも、安心してください。
実は “王道レイアウト” を覚えておけば 90% 迷いは消えます。

この記事ではそのベストプラクティスを、理由付きでスッキリまとめていきます。


結論:まずは「src レイアウト」を採用せよ

現代の Python プロジェクトは srcレイアウト一択 と言っても過言ではありません。

my_project/
├─ pyproject.toml
├─ README.md
├─ LICENSE
├─ src/
│   └─ my_project/
│       ├─ __init__.py
│       ├─ core/
│       ├─ infra/
│       └─ cli.py
└─ tests/

この形にするだけで:

  • “ローカルパスで import が動く” 事故が減る
  • pip install -e . で開発が超スムーズ
  • テストが本番コードを本当に import できているか確認しやすい

というメリットがドカッと手に入ります。


pyproject.toml を中心に管理する

昔のように setup.py を書く必要はありません。
現代の Python は pyproject.toml が主役。

最小構成は次の通り:

[project]
name = "my-project"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = ["requests"]

[project.optional-dependencies]
dev = ["pytest", "mypy", "ruff"]

[project.scripts]
my-cli = "my_project.cli:main"

ポイント:

  • namesrc/my_project/ のフォルダ名を揃える
  • CLI を作るなら [project.scripts] に書くだけでコマンド化
  • dev 依存は optional-dependencies で管理するとキレイ

Poetry や Hatch を使う場合も考え方は同じです。


ディレクトリ構成の考え方(役割で分ける)

Python は「自由にファイル置いてOK」なので、逆にカオスになりがち。
そこで 役割ごとパッケージ分割 がおすすめ。

src/my_project/
├─ core/        # ドメインロジック
├─ infra/       # DB/API/外部I/O
├─ cli.py       # CLI entry point
└─ __init__.py

役割分割の例

ディレクトリ 中身
core/ 業務ロジック、サービスクラス
infra/ DB、外部API、ファイルI/O
cli.py 実行エントリポイント
__init__.py Public API の整理

「core」と「infra」みたいにレイヤー分けすると、
Clean Architecture 的にも美しい構造になります。


テストは必ずプロジェクト直下の tests/ に集める

tests/
├─ __init__.py     # 空でOK(pytest的にはなくてもOK)
├─ test_core_service.py
├─ test_models.py
└─ cli/
   └─ test_cli.py

なぜ分けるの?

  • 本番ロジックと混ざらず見通しが良い
  • pytest が自動でテストを発見
  • src に混ぜると import バグの温床になる

pytest の設定は pyproject.toml に書くとシンプル:

[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "-ra"

設定値は config.py、環境差分は環境変数へ

Python アプリでよくある問題:

  • 本番用 API URL がコードに埋め込まれている
  • .env を読み込んでない
  • 設定が散乱する

これを防ぐには、Pydantic BaseSettings を使うのが最強です。

# src/my_project/config.py
from pydantic import BaseSettings

class Settings(BaseSettings):
    api_url: str = "https://api.example.com"
    debug: bool = False

    class Config:
        env_file = ".env"

settings = Settings()

型 / Lint / Formatter を最初から入れておく

後から入れると地獄を見るので “最初に” 入れるのが鉄則。

  • 型:mypy or pyright
  • Lint:ruff
  • Formatter:ruff format or black

設定も pyproject.toml にまとめるのがベスト。

[tool.mypy]
strict = true
packages = ["my_project"]

[tool.ruff]
line-length = 100
target-version = "py311"

よくあるアンチパターン

反面教師としてよくある地雷もまとめておきます。

アンチパターン なぜ悪い?
main.py, utils.py, helper.py が直下に散乱 どこが何をするファイルか不明瞭
テストを src 内に置く import が壊れる・汚れる
プロジェクト直下に大量の .py 大規模化した瞬間に破綻
venv をリポジトリにコミット 重いし無意味。.gitignore

特に utils.py 依存のプロジェクトはだいたい後で泣きます。


まとめ

my_project/
├─ pyproject.toml
├─ README.md
├─ src/
│   └─ my_project/
│       ├─ core/
│       ├─ infra/
│       ├─ cli.py
│       └─ __init__.py
└─ tests/
  • src レイアウト
  • テストは tests/
  • 設定は Pydantic BaseSettings
  • 型・Lint・Formatter を早めに導入
  • すべて pyproject.toml に集約

Python プロジェクトはこの形にしておけば、
後から拡張する時も破綻しません。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?