【超快適】Python仮想環境の使い回し。Jupyter＆FastAPI用テンプレを作ってみた

# はじめに
Python学習や検証をしていて「毎回環境整えるのめんどくさい…」「ライブラリ何入れたんだったか…」と思ったことはありませんか？

自分の学習＆おさわり用に作った「仮想環境テンプレ」 
JupyterLabやFastAPIなどのプロジェクトで即使える構成を整え中。

## なにがあった？

### 😱 pip install jupyterlab ができない！？（brewのPython）

最初、以下のようにインストールしようとして…

```bash
pip install jupyterlab
```

こんなエラーが…！
仕事でPython触ってたときにこんなことなかったわよ！どゆことなの？？

```bash
error: externally-managed-environment

× This environment is externally managed
╰─> To install Python packages system-wide, try brew install
    xyz, where xyz is the package you are trying to
    install.
```

<details>

```bash
ayuko@macbook projects % pip install jupyterlab
error: externally-managed-environment

× This environment is externally managed
╰─> To install Python packages system-wide, try brew install
    xyz, where xyz is the package you are trying to
    install.
    
    If you wish to install a Python library that isn't in Homebrew,
    use a virtual environment:
    
    python3 -m venv path/to/venv
    source path/to/venv/bin/activate
    python3 -m pip install xyz
    
    If you wish to install a Python application that isn't in Homebrew,
    it may be easiest to use 'pipx install xyz', which will manage a
    virtual environment for you. You can install pipx with
    
    brew install pipx
    
    You may restore the old behavior of pip by passing
    the '--break-system-packages' flag to pip, or by adding
    'break-system-packages = true' to your pip.conf file. The latter
    will permanently disable this error.
    
    If you disable this error, we STRONGLY recommend that you additionally
    pass the '--user' flag to pip, or set 'user = true' in your pip.conf
    file. Failure to do this can result in a broken Homebrew installation.
    
    Read more about this behavior here: <https://peps.python.org/pep-0668/>

note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
hint: See PEP 668 for the detailed specification.

```

</details>

これは、最近のmacOS＋Homebrewで導入された「PEP 668」という制限が原因

● 簡単に言うと：

HomebrewのPythonは「自分で管理するから pip で勝手に書き換えないでね」というスタンスになったため、pip install しようとするとエラーになるようになったのだそう。

🔧 PEP 668 とは？

正式には「PEP 668: Marking Python base environments as externally managed」
Pythonパッケージ管理のトラブルを防ぐために、システム全体で使うPython（＝ベース環境）に直接pip installできないようにするルール。(´－｀)。oＯ( 知らんかった )
 - [PEP 668](https://peps.python.org/pep-0668/)

● 解決策：仮想環境を使う！
```bash
# 仮想環境を作成
python3 -m venv venv

# 仮想環境を有効化
source venv/bin/activate

# よく使いそうなライブラリをインストール
pip install pandas numpy jupyterlab matplotlib seaborn scikit-learn ipykernel
pip install jupyterlab

# JupyterLabで使えるようにカーネルを登録
python -m ipykernel install --user --name=venv --display-name="Python (venv)"

# 今の仮想環境のパッケージを保存 <-- 👀ココが今回の学びのPoint
pip freeze > requirements.txt

```

無事にJupyterLabは起動できました。

そこで学びました。こんなお手軽なPython仮想環境。
**自分の学習👩‍💻＆お触り用🖐️ならわざわざDockerにしなくても十分**じゃないの。


## 🔧 仮想環境の作成と基本操作（復習）

- `python3 -m venv venv`
- `source venv/bin/activate`
- `pip install -r requirements.txt`

## ぐちゃぐちゃになったら… 捨てて作り直す！

```bash
rm -rf venv/
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt  # ← 必要なライブラリだけ再インストール！
```

## ライブラリのバージョン管理Tips

| 操作| コマンド |
|:-|:-|
|  アップデート可能なパッケージを確認 | `pip list --outdated`  |
|  すべてまとめてアップデート | ```pip list --outdated --format=freeze | cut -d = -f 1 | xargs -n1 pip install -U  |
| バージョン固定で保存（再現性重視）  | `pip freeze > requirements-locked.txt` |
---

## 仮想環境でJupyterLabとFastAPIをサクッと試すテンプレ作った

### ディレクトリ構成

```
python-env-templates/
├── base-ds/
│   ├── requirements.txt
│   └── README.md
├── fastapi-demo/
│   ├── requirements.txt
│   ├── main.py
│   └── README.md
└── README.md
```

## 

### データ分析基本セット
```txt
# requirements.txt
pandas
numpy
matplotlib
seaborn
scikit-learn
jupyterlab
ipykernel
```

### Fast APIお触りセット (基本セットに追加してインストール)

```txt
# requirements.txt
fastapi
uvicorn
```


```python
# main.py
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"message": "こんにちは、FastAPIのサンプルコードだよ！"}

@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = None):
    return {"item_id": item_id, "query": q}
```

# 最後に

Dockerなしでもシンプルに構築できる仮想環境は、環境構築のトラブルを避けるだけでなく、自分だけの「お試しスペース」としても最適。チーム開発で配布してハンズオンするのにもいいね！