Python & VSCode & Notebook 環境を uv + Ruff を利用した上でいい感じに整える!

この記事は Zen Study プログラミングコース Advent Calendar 2024 の 4 日目の記事の予定でした。大遅刻ごめんなさい！

# Python & VSCode & Notebook 環境を uv + Ruff を利用した上でいい感じに整える！

この記事では VSCode 上で Jupyter Notebook 環境を整えることを目指します！

ただ、解説込みの実践形式になっていて、手順を忘れたときの簡単に参照したい用途に向かなそうなので、後日手順のみ純粋に切り出した記事も出そうと思います。

## 要旨

この記事は以下の三段構成です。

1. uv を利用して Python 環境を構築する
1. VSCode 上に Jupyter Notebook 環境を構築する
1. Ruff で Format と Lint を効かせる

また、Mac ユーザ向けの説明となっています。Windwos ユーザ向けの環境構築は余裕があれば、別記事で出そうと思います。

## 記事執筆の動機と技術選定

環境構築をサッとしたい方はこの節を読み飛ばしていただいて構いません。

次の節: [uv を利用して Python 環境を構築する](#uv-を利用して-python-環境を構築する)

### 動機

私はデータサイエンス系の学部に所属する B2 であり、講義でよく Python と Jupyter Notebook を利用します。講義だとそんな Python ゴリゴリに書くことはありませんが、今後のことを考えておくと、きちんとした環境構築の術を知っておいた方がつまづかないだろうなという気持ちになったのでやってみました。

### 技術選定について

備忘録の側面もあるので、なぜこれらのツールを選定したかという部分はこの節に分離して書いておきます。

ざっくばらんに書いているので、事実関係に齟齬のある部分が存在するかもしれません。その場合はお手数ですがご指摘いただけると嬉しいです。

まず、今回利用しているツールやソフト、言語は以下の通りです。

- Python
- VSCode
- Jupyter Notebook
- uv
- Ruff

まず、Python と VSCode、Jupyter Notebook について書きます。

### Python と Jupyter Notebook、VSCode について

Python はデータサイエンスだと定番の言語ですね。かなり気軽にかけて便利です。

Jupyter Notebook は一つのファイルにコードとその実行結果、およびマークダウンをまとめられます。また、ファイルに記述されているコードはそのまま実行できます。そのため、動くレポートのようなものを手軽に作って共有できます。データサイエンス系だとよく見かける印象です。

VSCode は定番のエディタですね。いつも使わせていただいています。

せっかくであれば、Jupyter Notebook を VSCode 上で利用できると使い勝手が同じになって嬉しいです。さまざまな拡張機能が使えたり GitHub Copilot が使えたりしてとても便利です。

なお、純正の Jupyter Notebook は、サーバを立ててブラウザ上で開く形ですので、自動補完機能がなくて私からすると若干辛い部分があります。私が知らないだけで補完機能があったらごめんなさい。

### uv と Ruff について

次に、uv と Ruff を紹介します。

uv は Rust で作成された、とても高速な Python パッケージマネージャかつプロジェクトマネージャです。
また、さまざまなツールの機能を包括しており、これ一つでいろんなことができます。

https://docs.astral.sh/uv/

公式サイトでも主張されている通り、動作が大変軽いです。複数のパッケージを Install する際、pip を使う場合よりもずっと速く Install が終わります。

仮想環境の作成も venv よりもずっと早いみたいです。以下の uv 公式ブログにおいて仮想環境を作成動作の速度比較が載っています。

https://astral.sh/blog/uv

仮想環境について補足すると、パソコン 1 台に 1 つの Version しか Python を入れられないところを、仮想環境によって複数の Version が並立できるようにするものです。

Ruff は Linter と Formatter の機能を持っています。

Linter とはソースコードを書くルールに沿ってコードが書かれているかチェックしてくれるツールです。Lint をかけると言いますね。
Formatter とは、コードの見た目を整えてくれるツールです。こちらも Format をかけると言います。

複数人でのコーディング時に、全員が読みやすい状態にできる便利な存在です。

これも uv と同じ開発元が提供しているツールであり、既存のツールよりもずっと高速であるという比較が公式サイトで確認できます。

https://docs.astral.sh/ruff/

Lint する際に用いるルールはコーディングルールと呼ばれるものです。複数のルールがありますが、 Python だと [PEP 8](https://peps.python.org/pep-0008/) というルールが一番有名でしょう。私の認識が正しければ、これは Python 公式によって用意されているルールです。

Ruff では複数のルールをまとめてチェックしてくれます。ルールは必ずしも守るべきものというわけではありません。読みやすいことが大事ですから、自分たちのやり方とそぐわないルールは無視しても良いです。

Ruff を使う際にも、使わないルールは無効化できます。

大学だと複数人でコーディングはしませんが、人にコードを見せる際は綺麗なコードを見せたいものです。特に、先生に提出するコードであれば尚更です。

また、なぜ Lint されたのか理由もわかるので、自分のコードの悪癖を直すきっかけにもなります。

というわけで Ruff を利用して Lint してくれるようにします。

Lint を手動でやるのは面倒なのでファイル保存時に Ruff が動くようにしています。

ちなみに、uv と Ruff の開発元は同じ Astral です。Ruff の開発が先で、2024 年になって uv の開発も始めたようです。



## uv を利用して Python 環境を構築する

uv を利用して Python 環境を試しに一つ構築するところまでやってみます。

### uv を Install する

では uv を Install してみましょう。

公式サイトを見るとさまざまな Install 方法が用意されています。お好きな方法でダウンロードしてみてください。

https://docs.astral.sh/uv/getting-started/installation/#installation-methods

私は brew でツールを Install することが多いので、今回も brew で Install することにしました。

brew の場合は以下のコマンドで Install できます。

```sh
brew install uv
```

### uv で利用できる Python を Install する。

uv が Install できましたので、次は uv で利用する Python を Install します。

以下のコマンドを使うと uv で利用できる Python の Version や既に Install した Version を確認できます。

```sh
uv python list
```

実行結果は以下のように表示されます。uv を利用して Install できる場合は `<download available>` と表示されます。既に Install 済みの場合は Install されている場所のパスを表示してくれます。

```sh
cpython-3.13.0rc2-macos-aarch64-none    <download available>
cpython-3.12.7-macos-aarch64-none       /opt/local/bin/python3.12 -> /opt/local/Library/Frameworks/Python.framework/Versions/3.12/bin/python3.12
```

最新版の Python を Install する場合は以下のコマンドで行えます。

```sh
uv python install
```

Version を指定する場合には、以下のコマンドを入力します。Install の後に Version 指定を挟むだけですね。

```sh
uv python install 3.12
```

uv での Python Install 方法についてより詳細に知りたい方は公式ドキュメントを参照してみてください。

https://docs.astral.sh/uv/guides/install-python/

### プロジェクトの作成

uv 環境の Python の Install が完了したので、プロジェクトの作成に入ります。

プロジェクトを作成することで、依存ライブラリや使用しているツールをプロジェクト単位で管理できます。

まずは適当なディレクトリを作成して、その中でプロジェクトを作成してみます。今回は `test-uv` という名前にします。

```sh
mkdir test-uv
```

以下のコマンドで、3.12 の Python を使用する、`example` という名前のプロジェクトを作成できます。

`-p` は `--python` と同じで、利用する Python の Version を指定するためのオプションです。

```sh
uv init example -p 3.12
```

無事に作成されると、以下のような表示が出るかと思います。

```sh
Initialized project `example` at `/Users/username/test-uv/example`
```

プロジェクトを初期化したという意味ですね。

また、プロジェクト用のディレクトリも新規作成されているはずです。`ls` コマンドで `example` フォルダが確認できます。

プロジェクトの作成については公式ドキュメントも合わせてご参照ください。

https://docs.astral.sh/uv/guides/projects/

https://docs.astral.sh/uv/reference/cli/#uv-init

以上でプロジェクトの作成ができるようになりました！

## VSCode 上に Jupyter Notebook 環境を用意する。

プロジェクトを作成できたので、次は VSCode 上に Jupyter Notebook 環境を用意していきます。

### 必要な拡張機能の Install

Jupyter Notebook 環境を用意するために、必要な拡張機能を Install します。

推奨される拡張機能は、初回の Jupyter Notebook の Kernel 選択時に Install するか聞かれますので、これに沿って Install するのが一番楽かと思います。

先ほど作成したプロジェクトのフォルダに移動します。

```sh
cd example
```

合わせて `example` フォルダを VSCode で開きます。`code example` で開くのが一番楽でしょう。

:::note warn
注意
ここから先は `example` フォルダ内にて作業をしてください。

VSCode でも、`example` フォルダをトップフォルダとして開いてください(VSCode の新しいウィンドウから、「開く」でフォルダを開いた状態)。
そうでないと VSCode の設定が他のフォルダに適用される場合があります。
:::

次に、`test.ipynb` というファイルを作成します。

次に、開いた画面において右上に "Select Kernel" とあるため、それをクリックすると以下のように Python と Jupyter 用の推奨される拡張機能を Install するか聞かれます。それをクリックして推奨される拡張機能を Install しておくと間違いはないはずです。

![vscode_jupyter.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266262/1678d7e1-6fed-da32-b1d6-b423e752ed75.png)

もし、手動でこれらの VSCode 側から推奨される拡張機能を Install したい方のために、これをクリックして Install される拡張機能を以下に示します。拡張機能が公開されている Marketplace へのリンク付きです。詳細を確認したい場合はそちらも合わせてご確認ください。

- [Jupyter](https://marketplace.visualstudio.com/items?itemName=ms-toolsai.jupyter)
- [Jupyter Cell Tags](https://marketplace.visualstudio.com/items?itemName=ms-toolsai.vscode-jupyter-cell-tags)
- [Jupyter Keymap](https://marketplace.visualstudio.com/items?itemName=ms-toolsai.jupyter-keymap)
- [Jupyter Notebook Renderers](https://marketplace.visualstudio.com/items?itemName=ms-toolsai.jupyter-renderers)
- [Jupyter Slide Show](https://marketplace.visualstudio.com/items?itemName=ms-toolsai.vscode-jupyter-slideshow)
- [Pylance](https://marketplace.visualstudio.com/items?itemName=ms-python.vscode-pylance)
- [Python](https://marketplace.visualstudio.com/items?itemName=ms-python.python)
- [Python Debugger](https://marketplace.visualstudio.com/items?itemName=ms-python.debugpy)

### Kernel の作成

VSCode 側で必要な拡張機能の Install が完了しましたので、次は uv を利用して Jupyter Notebook を動かすのに必要な機能を Install していきます。

まず、作成したプロジェクトで用意した Python 仮想環境を Kernel として動作させるために必要なパッケージを Install します。

```sh
uv add --dev ipykernel
```

この ipykernel パッケージによって、Jupyter Notebook の実行が可能になります。

なお、プロジェクト作成後初めてのパッケージの Install では、設定に応じた仮想環境も作成され、`.venv` というフォルダが作成されます。

プロジェクトフォルダを開いた上で `.venv` フォルダがあると、以下の画像のように、VSCode で選択可能な Kernel として認識してくれるはずです。


![vscode_select_kernel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266262/b1dde55f-7b1e-893a-a007-57d1c0985393.png)

右上の Kernel の表示が選択した Kernel になっていれば問題ありません。

![kernel_version.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266262/9862ea1f-f545-4e02-6ed2-db65a17ca6c1.png)

:::note
uv と Jupyter Notebook

uv 公式で Jupyter Notebook で使う際の方法についていくつか紹介されています。私が行った以外の方法を行いたい方はこちらもご参照ください。

https://docs.astral.sh/uv/guides/integration/jupyter/#using-jupyter-from-vs-code

:::

### Jupyter Notebook 上でプログラムを実行してみる。

ここまでで Jupyter Notebook を VSCode 上で動かせる環境が整いましたので、実際に動かしてみましょう。

「+ Code」 と書かれた部分をクリックすることで Python コードを実行するためのセルというものを作成できます。

セルはコードの実行単位のようなものです。Jupyter Notebook ではセルごとにコードを実行できます。

セルに、以下のコードを入力してください。

```py
print("Hello Jupyter!")
```

入力したら、セルの左側にある再生ボタン(`▷`) を押してコードを実行できます。

以下のように、`Hello Jupyter!` と表示されていれば問題なく動いています。

![code_executed.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266262/7dd39f99-3681-7ebd-5bed-3f4d0e11254e.png)

ここまでで、VSCode 上で Jupyter Notebook を動かせる環境が整いました！

### uv を使って、パッケージを追加してみる

データサイエンス系だと numpy や pandas、matplotlib をよく使うかと思います。

これらをプロジェクトに追加して、利用できる状態にする手順を確認します。

以下のコマンドによって、プロジェクトに numpy と pandas、matplotlib を追加できます。

```sh
uv add numpy pandas matplotlib
```

このように、`uv add` コマンドによってプロジェクトに好きなパッケージを追加できます。

追加した numpy の動作確認をしてみます。

以下のコードを新しいセルに追加して実行できることを確認してみてください。

```py
import numpy as np

a = np.array([1,2,3])

print(a)
```

エラーが出ずに実行されれば問題ありません。

もし、追加したパッケージを削除したい場合は、`uv remove` コマンドを使って削除できます。

- [uv add の Reference](https://docs.astral.sh/uv/reference/cli/#uv-add)
- [uv remove の Reference](https://docs.astral.sh/uv/reference/cli/#uv-remove)

次の節からは、Linter である Ruff の設定を行います。

## Ruff による Lint & Format 設定

最後に Ruff により Lint と Format が行えるようにしましょう。

Lint & Format 結果は VSCode 上で確認できるようにしておきます。合わせて、Lint & Format 結果を元にしたコード修正を保存時に行います。

### VSCode に Ruff の拡張機能を Install

まず、VSCode に Ruff の拡張機能を Install します。

[Ruff の VSCode 拡張機能](https://marketplace.visualstudio.com/items?itemName=charliermarsh.ruff)

Install しただけで VSCode 上で Ruff はすぐに動いてくれます。

試しに、`test.ipynb` に Lint されるコードを貼って、Ruff が動くことを確認しましょう。

以下の `{}` がない f-string 表示させるコードを新しいセルに追加してみてください。

```py
print(f"f-string")
```

すると、Ruff によって Linting されて、以下のように黄色の波線がつくと思います。

![ruff_linting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266262/b935eb6e-b2bb-22dc-a610-7bee98092c27.png)

マウスをホバーさせてみると、どのような指摘なのかを確認できます。

![ruff_linting_hover.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266262/472150c8-7463-d6bc-bdf1-1f76ad04ec40.png)

このように、f-string を使っているのに `{}` 使っていないよという指摘がされており、Ruff が動いていることがわかります。

ここで、`Ruff(F541)` と書かれている部分をクリックすると Ruff の公式サイトに飛べて、ルールの詳細を確認できます。

`Quick Fix...(⌘.)` と書かれている部分を押すと、波線部分の対応を選べます。

![ruff_quick_fix.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266262/343d2efb-3456-3c11-23e4-e08bebb6f8f4.png)

上の選択肢は、Ruff の指摘に沿って修正をかける選択で、下の選択肢は、コードを変更しないでこの行にあたっている指摘を無視する選択です。

Ruff ではコメントによって、ある行への指摘を無視できます。

書き方は公式サイトを参照してみてください。

https://docs.astral.sh/ruff/linter/#error-suppression

### 保存時に自動でコード修正が行われるようにする

VSCode の設定を変更して、保存時に Ruff による Lint & Format 結果を元に自動修正が行われるようにします。

まず、VSCode の左下にある歯車マークをクリックして、「Settings」を選択してください。日本語で VSCode を利用している場合は「設定」と書かれている場所です。

設定画面が開かれたら、右上に三つマークが並んでいると思います。そのうちの一番左の、ファイルの後ろから矢印が表に出ているアイコンをクリックしてください。

![how_to_open_settings_json.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266262/bc70c48d-9f1b-0209-5dd9-bb74c18b968d.png)

これをクリックすると、設定を json ファイル形式で開けます。

最初は何も設定がないので、以下のように空の状態です。

![default_settings_json.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266262/6e98c017-f025-aca2-aecd-6c0d14d08374.png)

このファイルを、以下の記述となるように編集してください。

```json
{
    "[python]": {
        "editor.formatOnSave": true,
        "editor.codeActionsOnSave": {
            "source.fixAll": "explicit",
            "source.organizeImports": "explicit",
        },
        "editor.defaultFormatter": "charliermarsh.ruff",
    },
    "notebook.formatOnSave.enabled": true,
    "notebook.codeActionsOnSave": {
        "notebook.source.fixAll": "explicit",
        "notebook.source.organizeImports": "explicit",
    },
}
```

記述後は `settings.json` をきちんと保存してください。

これらの記述によって、Python ソースコードと Jupyter Notebook 上の Python コードセルが、ファイル保存時に自動的に修正されます。

Lint の指摘によっては自動で修正できないものもありますので、それは自分で対応しなければなりません。どの指摘が修正されるかは[ルール表](https://docs.astral.sh/ruff/rules/)を見ると確認できます。

VSCode の Ruff 拡張によって修正されるのは、Lint の指摘と コード内の Import 文の並び順です。

ここら辺の記述方法や挙動についてより詳細に知りたい方は Ruff 拡張機能の Overview > Configuring VS Code の節を参照してみてください。 

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

### コード修正が行われることを確認する。

では、先ほどの変更が正しく反映されているのか確認します。`test.ipynb` にて Lint が当たる f-string を記述したと思います。

コードの自動修正を有効にしたので、ファイル保存時にこの f-string は修正されるはずです。

実際にファイルを保存して、修正されることを確認してみてください。

自動保存を有効にしている場合、保存をショートカットでしてあげないと自動修正されないかと思いますので、保存のショートカットキーを叩いてみてください。

:::note info

今回設定したのは VSCode の拡張機能として提供されている Ruff です。

uv を利用して Ruff をプロジェクトに Install して commit を行った際に Lint & Format させるようにもできるはずです。

この記事では扱いませんが、「Ruff git commit」あたりの単語で検索すると、これらの解説記事があるかと思いますので、そちらを参照してみてください。

:::

以上で Ruff による自動修正が行われるようになりました！

## 終わりに

ここまでお読みいただきありがとうございました！

この記事では、uv による Python プロジェクトの作成と VSCode 上への Jupyter Notebook 環境を構築、Ruff による Lint & Format ができるようにしました。

自分が行った環境構築をまとめてみようということで書きました。構成としてもっとよくできた気がしますが、形になったのでよしとします。

それと本当はアドカレ用の記事なのに年明けの公開となってしまって大変申し訳ないです :bow: 
もう一つの GitHub Actions を扱うアドカレ記事も早めに書き上げます……。

GitHub Actions の記事では Organaization で使う際の便利な使い方について取り上げるつもりです。

ハンズオン形式になってしまって、手順を簡単に参照したい際に読みづらいと思うので、今後、もっとシンプルに手順を記載した記事を出してリファレンス的に確認できるものを出そうと思います。



誤りや誤字などありましたらご指摘いただけますとありがたいです :pray:

<!--

uv の機能を利用して、仮想環境を一つ構築してみる。

ついでにパッケージのインストールもする。

これが第一章の内容

第二章は VSCode 上に Jupyter Notebook 環境を用意する話

第三章は用意した環境に、Ruff による Format&Lint を効かせるようにする話

-->

## 参考文献

- https://gihyo.jp/article/2024/03/monthly-python-2403
  uv を使ってみようという記事で、わかりやすいので大変おすすめです
- https://gihyo.jp/article/2023/03/monthly-python-2303
  同じ技術評論社の媒体で掲載されている Ruff の解説記事
  こちらもわかりやすいです。