PythonプロジェクトにAIコーディングルールが必要な理由は明確です。Pythonは許容度が高い言語なので、プロジェクト固有のガイドなしにAIアシスタントを使うと、技術的には正しいが自分のコードベースに合わない出力が得られます。フォーマッタ、型システム、テストパターン、パッケージ管理、環境管理はプロジェクトによって異なります。明示的なルールがなければ、AIツールは合理的な推測をしますが、その推測は多くの場合あなたのセットアップには合いません。
本記事ではPythonプロジェクト向けのCLAUDE.mdと.cursorrulesの実用テンプレートをドメイン別(型ヒント、テスト、パッケージング、環境管理、非同期パターン)に解説します。実際のプロジェクトのPython固有ルールはギャラリーで確認できます。
全プロジェクト共通のコアルール
Pythonプロジェクトのスタックに関わらず、すべてのAI設定ファイルに含めるべきルールです:
## Pythonバージョンとランタイム
- Python 3.11+必須
- 文字列フォーマットはf-strings(.format()や%は使わない)
- ファイル操作はos.pathではなくpathlib.Pathを使う
- 想定済みの例外にはbearer except blockではなくcontextlib.suppress()を使う
## 型ヒント
- 全関数シグネチャに型ヒント必須(パラメータ + 戻り値)
- 全ファイルの先頭に`from __future__ import annotations`を記述
- ユニオン型は`X | Y`構文を使う(Optional[X]やUnion[X, Y]は不可)
- 組み込みジェネリクスを使う:List[str]ではなくlist[str]、Dict[str, int]ではなくdict[str, int]
- 関数間で受け渡されるdictの形状にはTypedDictを使う
## コードスタイル
- Blackでフォーマット(行の長さ:88)
- isortでインポート順序(profile = black)
- ruffでリント
- 実行コマンド: black . && isort . && ruff check .
from __future__ import annotationsについて補足します。これはPEP 563の遅延評価を有効にし、型ヒントでの前方参照を許可し、Python 3.9でのランタイムエラーを防ぎます。コードベースが3.9をターゲットにしている場合、これは省略できません。
型ヒントの実践
型ヒントはAI生成のPythonコードが最もよく修正が必要になる部分です:
## 型ヒントルール
### Optional[X]ではなくX | Noneを使う
# Bad
from typing import Optional
def get_user(id: int) -> Optional[str]:
# Good
def get_user(id: int) -> str | None:
### 戻り値の型は必須
# Bad
def process_data(items):
return [x * 2 for x in items]
# Good
def process_data(items: list[int]) -> list[int]:
return [x * 2 for x in items]
### 複雑なdictにはTypedDictを使う
from typing import TypedDict
class UserConfig(TypedDict):
name: str
role: str
permissions: list[str]
### 構造的型付けにはABCよりProtocolを使う
from typing import Protocol
class Closeable(Protocol):
def close(self) -> None: ...
プロジェクト構造ルール
AIツールがファイルを正しい場所に置くために、プロジェクトのレイアウトを明示します:
## プロジェクト構造
src/
mypackage/ # メインパッケージ
__init__.py
models/ # dataclasses、TypedDicts、Pydanticモデル
services/ # ビジネスロジック
api/ # HTTPハンドラ
utils/ # 共有ユーティリティ
tests/
unit/ # 高速、I/Oなし
integration/ # DB/ネットワーク使用可
conftest.py # 共有フィクスチャ
## インポート規約
- 絶対インポートのみ(`from ..utils import foo`のような相対インポート禁止)
- 定数以外はモジュールをインポートする(コンテンツではなく):
- Good: import mypackage.utils as utils
- OK: from mypackage.constants import MAX_RETRIES
- Bad: from mypackage.services import create_user
テストルール
テストはPythonプロジェクトで最も設定が異なる部分です:
## テストセットアップ
- pytest(unittestは使わない)
- 非同期テストにはpytest-asyncio
- モックにはpytest-mockまたはunittest.mock
- テストコマンド: pytest tests/ -v --tb=short
- カバレッジ: pytest --cov=src/mypackage --cov-report=term-missing
## テスト記述ルール
- ファイル命名: tests/ディレクトリ内のtest_{module_name}.py
- 関数命名: test_{何を}_{条件}_{期待する結果}
- 共有セットアップにはフィクスチャを使う(setUp/tearDownではなく)
- 真偽値だけでなく具体的な値をアサート: `assert result` ではなく `assert result == expected`
- システムの境界でモックを設定する(内部ではなく)
- テストでtime.sleep()を使わない — freezegunやモックdatetimeを使う
## テストのサンプルパターン
import pytest
from unittest.mock import AsyncMock, patch
from mypackage.services import UserService
@pytest.fixture
def user_service() -> UserService:
return UserService(db=None)
async def test_get_user_returns_none_when_not_found(
user_service: UserService,
) -> None:
with patch.object(user_service, "db") as mock_db:
mock_db.fetch_one = AsyncMock(return_value=None)
result = await user_service.get_user(id=999)
assert result is None
環境・依存関係管理
指定がないと最も摩擦が生まれる部分です:
## 環境管理
- パッケージ管理にuv(pip/poetry/pipenvは使わない)
- 仮想環境: プロジェクトルートの.venv/(作成コマンド: uv venv)
- インストールコマンド: uv pip install -e ".[dev]"
- requirements.txtに直接パッケージを追加しない — pyproject.tomlを使う
## pyproject.tomlの規約
[project]
name = "mypackage"
requires-python = ">=3.11"
dependencies = [
"httpx>=0.27",
"pydantic>=2.0",
]
[project.optional-dependencies]
dev = [
"pytest>=8.0",
"pytest-asyncio",
"black",
"ruff",
"isort",
"mypy",
]
## pyproject.tomlではバージョンをピン留めしない(>=または~=を使う)
## requirements.lockでピン留めする(生成コマンド: uv pip compile pyproject.toml)
非同期Pythonのルール
非同期コードには同期コードより多くの落とし穴があります:
## 非同期ルール
- 並列I/Oにはasyncio.gather()(順次awaitではなく)
- タイムアウトにはasyncio.timeout()(Python 3.11+。asyncio.wait_for()ではなく)
- 非同期関数内から.run()を呼ばない — awaitを使う
- 非同期関数内でブロッキング処理を行わない: time.sleep()禁止、ブロッキングI/O禁止
- 非同期コンテキストでのCPUバウンド処理にはanyio.to_thread.run_sync()
- requestsではなくhttpx.AsyncClient(requestsはブロッキング)
## よくある並列リクエストのパターン
# Bad(遅い)
result_a = await fetch(url_a)
result_b = await fetch(url_b)
# Good(並列)
result_a, result_b = await asyncio.gather(
fetch(url_a),
fetch(url_b),
)
Pythonプロジェクト向け完全CLAUDE.mdテンプレート
# Pythonプロジェクト — Claude Code指示
## 環境
- Python 3.11+
- パッケージ管理: uv
- 仮想環境: .venv/
- テスト実行: pytest tests/ -v
- リント: ruff check . && black --check .
- 型チェック: mypy src/
## コード規約
- 全ファイルの先頭にfrom __future__ import annotations
- 全関数シグネチャに型ヒント必須
- 文字列フォーマットはf-strings
- ファイル操作はpathlib.Path
- Blackフォーマット(行の長さ88)
## 型ヒント
- X | None(Optional[X]は禁止)
- list[str](List[str]は禁止)
- 複雑なdict形状にはTypedDict
- 構造的型付けにはProtocol
## テスト
- pytestのみ
- test_{何を}_{条件}_{期待結果}の命名
- 具体的な値をアサート
- システム境界でモック
## プロジェクト構造
- ビジネスロジック: src/mypackage/services/
- モデル: src/mypackage/models/
- テストはsrc/の構造をミラー
## 禁止事項
- 相対インポート
- ログにprint()(loggingモジュールを使う)
- ミュータブルなデフォルト引数
- ベアexcept句
- テストでのtime.sleep()
実際のPython固有ルールのサンプルはギャラリーで確認できます。CLAUDE.mdの一般的な書き方についてはCLAUDE.mdガイドも参照してください。