【Python】俺的モダン開発環境の共有(2024年版)

2024年末の最近において、僕がPython開発をする方法やツールを共有しようと思います。
使用するツールや設定方法は好みが分かれるものだと思いますが、一つの例として参考になれば幸いです。

前置きとして、エディタはVisual Studio Code（VS Code）を使用しています。

# ランタイム管理

uvを使用しています。  
https://docs.astral.sh/uv/

以前まではpyenvを使っていましたが、最近mise -> uvと乗り換えをしました。

<details><summary>Installation</summary>

```sh
curl -LsSf https://astral.sh/uv/install.sh | sh
```

</details>

miseやuvによるランタイム管理ではコンパイル済みのランタイムをダウンロード、配置するだけでインストールが完了するのが特長でpyenvと異なる点です。  
ビルド用パッケージ群が不要、かつ高速なのが利点です。

e.g.

```sh
# 利用可能なバージョン一覧を確認する
uv python list

# マイナーバージョンのうち最新版がインストールされる
uv python install 3.13
uv python install 3.12
# バージョンを固定してインストール
uv python install 3.12.7

# プロジェクトのPythonバージョンを固定する
uv python pin 3.12.7
```

# 仮想環境管理

上記と同様、uvを使っています。  
uv自体は pyproject.toml + uv.lock ファイルでプロジェクトの依存関係を管理するパッケージマネージャーです。

以下のようにしてvirtualenvやpoetryのように使用できます。

| NOT uv | uv |
|---|---|
| `python -m venv .venv` | `uv venv` |
| `pip install xxx` | `uv pip install xxx` |
| `pip install -r requirements.lock` | `uv sync` <br> ※uv.lock ファイルがある場合のみ|
| `poetry add [-D] xxx` | `uv add [--dev] xxx` |
| `poetry remove xxx` | `uv remove xxx` |

## Poetryの代用

既存のプロジェクトの依存関係管理にPoetryを使用している場合の対応方法です。  
uvは`poetry.lock`との互換性はないため一工夫します。

### 1. uvxを使う方法

uvのインストールに含まれているuvxを使えばpoetryをインストールする必要がありません。

```sh
$ cd path/to/my-project
$ uv venv && source ./venv/bin/activate

(my-project) $ uvx poery install
```

### 2. poetryをグローバルにインストールする方法

poetryをグローバルのツールとしてインストールして利用する方法もあります。  
ただ、uvだけだと「グローバルにインストールする」ことはできないようになっています（※標準のpipコマンドが同梱されていないため）。

私の場合はpipxを経由してpoetryをインストールしてローカルで利用できるようにしています（コマンドのタブ補完が利くので便利）。

```sh
$ # Install poetry w/pipx
$ sudo apt install pipx
$ pipx install poetry

$ # go to project
$ cd path/to/my-project
$ uv venv && source ./venv/bin/activate
(my-project) $ poery install
```

# 開発、デバッグ

## リンター、フォーマッター

ruffを使っています。  
https://github.com/astral-sh/ruff

リンターかつフォーマッターであり、Rust製で高速に動作します。

VSCode拡張機能もあり、開発中のシームレスな連携が可能です。

https://marketplace.visualstudio.com/items?itemName=charliermarsh.ruff

以下の設定ファイルを記述することでファイル保存の度にフォーマットが利くようになります。

```json:.vscode/settings.json
{
  "[python]": {
    "editor.formatOnSave": true,
    "editor.defaultFormatter": "charliermarsh.ruff"
  }
}
```

未フォーマットのコードを保存（Ctrl + s）する様子です。

![ruff-formatting.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154711/123b4f44-83bf-5d9e-c11e-139d0c7b871c.gif)


動作感はほとんどなく、保存と同時に快適にコード整形ができます。

## デバッグ、テスト

基本、VS Codeのデバッガーをセットアップするようにします。
これにより、例えばWebアプリの開発においてローカル起動したAPIにブレイクポイントを設置して詳細な動作を確認できるようになります。
公式ドキュメントはこちら https://code.visualstudio.com/docs/python/debugging

`.vscode/launch.json`ファイルに定義を記載します。
Djangoアプリケーションだと以下のような記述。

```json:.vscode/launch.json
{
    "configurations": [
        {
            "name": "Python デバッガー: Django",
            "type": "debugpy",
            "request": "launch",
            "args": [
                "runserver"
            ],
            "django": true,
            "autoStartBrowser": false,
            "program": "${workspaceFolder}/manage.py"
        }
    ]
}
```

![debug-django.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154711/1f8cbeac-d396-8032-a3c6-d7acbf67b4d3.gif)


ユニットテストにはpytestを使います。
pytestの使い方自体には特筆事項ありませんが、pytestもデバッガー連携できるようにするのがオススメです。

[Ctrl + Shift + p] > `Python: Configure Tests` > `pytest` > (テストディレクトリを選択)"

以下の定義が`settings.json`に追記されます。

```json:.vscode/settings.json
{
  "python.testing.pytestArgs": [
    "."
  ],
  "python.testing.unittestEnabled": false,
  "python.testing.pytestEnabled": true
}
```

以下が動作例です。

![debug-pytest.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154711/05d677aa-84a0-0583-121e-6e99e25f8c18.gif)

# まとめ

Pythonの開発を取り巻くツールや設定例を紹介しました。
特にリンター/フォーマッターやテストツールなどはプロジェクトを一から立ち上げる際には重要だと思うので、常に便利なものを追求していきたいですね。

「自分はこうしている」といった情報もコメントや引用で教えて頂けると嬉しいです。