pyenv + PoetryでPython環境構築（Linux/Windows/Mac共通）

今まではAnacondaとかPipenvを使ってましたが、いまいち使いにくく、pyenv + Poetryを使った環境がいい感じだったのでメモ。

Linux/Windows/Mac共通で動くと思いますが、Ubuntu（WSL）でしか動作確認はしてません。以下の手順はUbuntu（WSL）環境です。

## 要件

-   Pythonのバージョン管理
-   仮想環境・パッケージ管理
-   requirements.txtは使いたくないが、出力はできるようにしておきたい  
    （クラウド環境等で必要になることがあるため）
-   できればLinux/Windows/Mac共通で使いたい
-   エディタはVS Code（+ Remote WSL）を想定
-   データ解析用途にはあまり向かないかも

## 構成

-   WSL2: Windows上のLinux環境
-   anyenv: \*\*env系コマンド管理ツール
-   pyenv: Pythonバージョン管理ツール
-   Poetry: 仮想環境・パッケージ管理ツール

# 0. WSL2を導入する（Windowsのみ）

WSLのおかげでWindowsでもLinux環境が簡単に使えるようになったので、開発がかなりやりやすくなりました。手順は公式ドキュメントを参考に。

[Windows Subsystem for Linux (WSL) を Windows 10 にインストールする | Microsoft Docs](https://docs.microsoft.com/ja-jp/windows/wsl/install-win10)

## WSL2の注意事項

WSL2では問題点が2つあります。

1.  ~~スリープ時にWSL上の時刻がずれる~~ [**解決してました**](https://qiita.com/nakahara-d/items/2b7bab82025fbdb23672)

    [WSL2 date incorrect after waking from sleep · Issue #5324 · microsoft/WSL](https://github.com/microsoft/WSL/issues/5324)

    WSLを起動している状態でPC自体がスリープに入るとWSL上の時刻がずれます。
    時刻がずれていると`apt`や`git`でエラーが発生するようになるので結構困ります。
    一時的な対応として`sudo hwclock -s`を実行することでホストの時刻に同期させることができます。

2.  WSL環境ではUSBなどの外部デバイスが扱えない

    2021年4月現在、WSL2上でUSBを使う公式の方法はありません。

    [WSL 2 についてよく寄せられる質問 | Microsoft Docs](https://docs.microsoft.com/ja-jp/windows/wsl/wsl2-faq)

    >   現時点では、WSL 2 にはシリアル サポートや USB デバイス サポートは含まれていません。 Microsoft では、これらの機能を追加するための最適な方法を調査しています。

    USB over IPという技術で対応することもできるみたいですが未検証です。

# 1. anyenvをインストール

pyenvを含む\*\*env系コマンドの管理ツールです。pyenvをインストールするため、事前にインストールしておきます。

Ubuntu以外の環境はREADMEを参考にしてください。

[anyenv/anyenv: All in one for \*\*env](https://github.com/anyenv/anyenv)

```bash
# Install
git clone https://github.com/anyenv/anyenv ~/.anyenv
echo 'export PATH="$HOME/.anyenv/bin:$PATH"' >> ~/.bashrc
# Initialize
~/.anyenv/bin/anyenv init
```

# 2. pyenvをインストール

Pythonのバージョン管理ツールです。
複数のバージョンのPythonをインストールしてプロジェクトごとに切り替えることができます。
pyenvを使ってvirtualenvを管理することもできるのですが、ここではPythonのバージョン管理のみ使います。

先ほどインストールしたanyenvを使ってpyenvをインストールします。
PoetryのインストールでPythonを使用するため、最新バージョンをglobalに設定しています。

[pyenv/pyenv: Simple Python version management](https://github.com/pyenv/pyenv)

```bash
# Install pyenv
anyenv install pyenv

# Install Python
pyenv install 3.9.4
pyenv global 3.9.4
```

# 3. Poetryをインストール

Pythonの仮想環境・パッケージ管理ツールです。
以前からある`requirements.txt`を使ったパッケージ管理を、`pyproject.toml`を使って依存関係も扱えるようにした管理ツールです。
パッケージ管理と同時にvirtualenvを使った仮想環境も自動で作成、管理してくれます。

[python-poetry/poetry: Python dependency management and packaging made easy.](https://github.com/python-poetry/poetry)

```bash
# Install
curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py | python -
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
```

ここでPoetryの設定を1つだけ変更します。

```bash
poetry config virtualenvs.in-project true
```

これを設定するとvirtualenvがプロジェクトフォルダのルートに作られ、VS Codeが自動的に認識するようになります。

これでPython開発を始める準備ができました。

# 4. プロジェクトを始める

プロジェクトフォルダを作り、Pythonバージョンの指定、Poetryで初期化・モジュールインストールの流れでプロジェクトを始めます。

```bash
# ディレクトリを作る
mkdir python-project
cd python-project

# pyenvでPythonのバージョン指定
pyenv install 3.8.9
pyenv local 3.8.9
# poetryで初期化
poetry init
# pyproject.tomlを読み取り、インストール（virtualenvが作られる）
poetry install

# ライブラリ追加
poetry add <name>
# 開発用ライブラリ追加
poetry add -D <name>
# requirements.txtエクスポート
poetry export -o requirements.txt
```

# おまけ（自分用）

よく使うライブラリ

-   ~~autopep8~~ black: PEP8スタイルガイドに準拠したコード整形ツール
-   flake8: リンターツール
-   flake8-commas: 末尾のカンマをチェック
-   flake8-isort: import文の順序チェック
-   ~~flake8-quotes: シングル・ダブルクォーテーションの使用をチェック~~blackなら自動で整形される
-   mypy: 静的型付けするなら

```config
# .flake8に追記（一行の長さをblackのデフォルトに合わせる）
[flake8]
max-line-length = 88
```

```toml
# pyproject.tomlに追記（isortのフォーマットをblackに合わせる）
[tool.isort]
profile = "black"
```

# 最後に

Node.jsのnpmと似たような構成で管理できるので気に入ってます。

-   npm - poetry
-   package.json - pyproject.toml
-   package.lock - poetry.lock
-   node_module - .venv

これがPythonのデファクトスタンダードになってくれるといいなぁ。。