pyenv+PoetryでのPython環境構築方法を覚えられない人（私）のための手順書

# 手順
最初に作業の全体像を載せます。
基本的には以下の手順で進めるとPoetryの環境構築が完了するはずです。（筆者の環境はM1Mac）

| 項番 | 内容 | 作業概要 |
|:----:|:-------------|:----|
| 1 | [pyenvのインストール](#pyenvのインストール) | `brew install` |
| 2 | [pyenvからPython環境のインストール](#pyenvからpython環境のインストール) | `install` |
| 3 | [pyenvからインストールしたPython環境を使用する](#pyenvからインストールしたpython環境を使用する) | `local/global` |
| 4 | [Poetyrのインストール](#poetryのインストール) | `curl` |
| 5 | [Poetyrプロジェクトを作成する](#poetryのインストール) | `init` |
| 6 | [Poetryプロジェクトにライブラリを追加する](#poetryプロジェクトにライブラリを追加する) | `add` |
| 7 | [Poetryプロジェクトに指定されたライブラリをインストールする](#poetryプロジェクトに指定されたライブラリをインストールする) | `install` |
| 8 | [Poetryプロジェクトの仮想環境に入る](#poetryプロジェクトの仮想環境に入る) | `shell/source` |

# pyenv
![スクリーンショット 2023-04-27 0.51.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/965436/2bf87457-b27e-abc5-69ee-dfa020674072.png)

## pyenvのインストール


https://github.com/pyenv/pyenv

```sh 
brew install pyenv 
```

## pyenvからPython環境のインストール
```sh 
pyenv install 3.11.2
```

:::note info 
### Pythonバージョン一覧方法
#### install可能なPythonバージョンの一覧

```sh 
pyenv install -l
pyenv install --list
```

#### install済みのPythonバージョン一覧
```sh
pyenv versions
```
:::

:::note warn
### Tips of `Xcode Command Line Tools`
`pyenv install`を実行すると、たまに以下のエラーに遭遇する。

```sh
BUILD FAILED (OS X 12.6 using python-build 20180424)
configure: error: C compiler cannot create executables
See `config.log' for more details
```

これの原因として良くあるのが、`Xcode Command Line Tools`がインストールされていないか、バージョンが古くなっているパターン。

消してから再度入れ直すとうまくいくことがある。

```sh 
$ sudo rm -rf /Library/Developer/CommandLineTools
$ xcode-select --install
```
### Ask ChatGPT to explain Xcode Command Line Tools.
Xcode Command Line Toolsとは、macOSで開発作業を行う際に利用する一連のツールとユーティリティのセットです。主に以下の目的で使用されます。

C, C++, Objective-C, Swiftなどの言語でのプログラムのコンパイルやデバッグ
ライブラリやフレームワークのインストール
システムツールやサービスの開発・管理
Xcode Command Line Toolsは、最初からMacには入っていません。ただし、開発作業を行うためには、通常XcodeやXcode Command Line Toolsをインストールする必要があります。

pyenv installコマンドに影響がある理由は以下の通りです。

Xcode Command Line Toolsは、C言語やその他の言語で書かれたプログラム（Pythonも含む）のコンパイルに使用されるコンパイラ（clang）を提供します。Pythonのインストールには、Pythonのソースコードをコンパイルする必要があるため、Xcode Command Line Toolsが必要です。
古いバージョンのXcode Command Line Toolsは、新しいmacOSバージョンや新しいPythonバージョンと互換性がない場合があります。そのため、古いバージョンのXcode Command Line Toolsがインストールされていると、pyenv installコマンドでエラーが発生することがあります。
:::


## pyenvからインストールしたPython環境を使用する
```sh
pyenv local <version>
pyenv global <version>
```

:::note info 
### 既存のPython環境からpyenvのPython環境に入り直す
`pyenv install 3.X.X`や`pyenv local 3.X.X`を実行しても、`which python`してみると元々のPython環境のままになっていることがある。

その場合、以下のコマンドを`~/.zshrc`に追加し忘れていないかをチェックすると良い。
このコマンドは`pyenv`で作成した環境が正常に読み込まれるようにするもので、`pyenv init`と入力することでもガイドとして表示される。

```sh 
export PYENV_ROOT="$HOME/.pyenv"
command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
```

追加後`source ~/.zshrc`を実行してPythonの環境がpyenvに置き換わるっているか確かめる。
:::

# Poetry
![スクリーンショット 2023-04-27 1.02.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/965436/e2471189-9269-e4f9-ba94-d51c19317642.png)


## Poetryのインストール
公式では以下のコマンドでのinstallが推奨されている。
```sh
curl -sSL https://install.python-poetry.org | python -
```

https://python-poetry.org/docs/#installing-with-the-official-installer

:::note info
### 他のインストール方法
（非推奨）Python環境があれば、pipでもインストールできる。
```sh
pip install poetry
```
非推奨の理由としては下記の点などが挙げられる。
- pipがPoetryの依存関係を適切に解決できないことがあるため、正しく動作しない場合がある。
- pip installを使用すると、既存のPython環境に影響を与える可能性がある。
:::

:::note info
### Poetry自体のアップデート
以下のコマンドを実行する
```sh
poetry self update
```
:::

:::note warn
### Don't install in Anaconda Env. !!
Anacondaを使用していた場合、Anacondaの仮想環境の中でinstallしないように注意。Poetryの仮想環境内に入ろうとした時に下記のようなエラーが発生する。

```sh
Virtual environment already activated: /Users/<user_name>/opt/anaconda3/envs/<vertual_env_name>
```

- Anacondaの仮想環境から抜ける
```sh
conda deactivate
```

- Anacondaの仮想環境に自動で入らないようにする
```sh
conda config --set auto_activate_base False
```
:::

## Poetryプロジェクトを作成する

https://cocoatomo.github.io/poetry-ja/basic-usage/


カレントディレクトリに`pyproject.toml`を作成する。

```sh
poetry init
```

:::note info 
新規でディレクトリを作成して、そこからコードの記述を始めていく場合は、`poetry new`コマンドを実行する。
新規ディレクトリに`pyproject.toml`が作成される。

```sh 
poetry new <some_package>
```
:::

:::note warn
### Poetry Version 1.8.x ～ の新機能：package-mode
Version1.8以上からは規定で`package-mode`が`true`になっています。普通にPythonの実行環境を作る意図であれば`false`で問題ないため`pyproject.toml`に以下のように1行追加しましょう。

```toml:pyproject.toml
[tool.poetry]
name = "any_project_name"
version = "0.1.0"
package-mode = false # ここを追加
```

#### `package-mode = true`の用途
というのも`pakage-mode`という名の通り、このプロジェクトをパッケージとして公開/配布したい場合などに使うと便利なオプションです。

配布する以外にも、例えば上記の`pyproject.toml`で作成した仮想環境に入ると、そこでは`import any_project_name`のように使用することができるようになります。

::: 

## Poetryプロジェクトにライブラリを追加する

```sh
poetry add <package_name>
```

:::note info
### Python環境（.venvフォルダ）作成場所の指定
以下コマンドで、このプロジェクトで作成するPython環境をどこに置くかを設定できる。

```sh
poetry config virtualenvs.in-project true/false --local
```
- true
    - 格納場所：プロジェクトのルートディレクトリ
    - このプロジェクトでのみ参照可能
- false(default)
    - 格納場所：`~/Library/Caches/pypoetry/virtualenvs/`
    - どこからでも参照可能
- `--local`オプション
    - 指定すると、上記設定は現在のプロジェクトでのみに適応される
    - 指定しない場合はすべてのプロジェクトでこの設定を引き継ぐ


現在のプロジェクトの設定を確認したいときは以下のコマンドを実行する。

```sh 
poetry config virtualenvs.in-project
```

:::

## Poetryプロジェクトのライブラリをアップデートする

### poetry updateコマンドでアップグレードする
```sh
poetry update <package_name>
```

:::note warn
### updateコマンドでは`pyproject.toml`制約を超えるアップグレードはできないことに注意！

例えば以下の`pyproject.toml`がある場合、`poetry update openai`を実行しても、最新で`openai=0.27.xx`までのものにしかアップグレードできない。

> キャレット要件：メジャー、マイナー、パッチという番号群のうち0でない最も左の数字を、新しいバージョン番号が更新しない場合に、更新が許可されます。
```toml: pyproject.toml
[tool.poetry.dependencies]
openai = "^0.27.0"
```

`pyproject.toml`の制約内で、適合する最新バージョンにアップデートされる。
それ以上にアップグレードしたい場合は、`pyproject.toml`を直接編集する方法がある。
:::

### `pyproject.toml`を直接編集してアップグレードする

まずは、以下例のように`pyproject.toml`を編集する

- `pyproject.toml`を編集する際にどのVersionを指定するか迷った際は、[pypiのリリース履歴](https://pypi.org/project/openai/#history)が参考になる

```toml: pyproject.toml
[tool.poetry.dependencies]
openai = "^0.27.0" # -> "^1.12.0"
```

その後以下のコマンドを実行する

```sh
$ poetry lock
$ poetry install
```

:::note info
### `poetry lock`コマンドの必要性
`pyproject.toml`が更新されたとき：pyproject.tomlに新しい依存関係が追加されたり、既存の依存関係のバージョン範囲が変更された場合、poetry.lockファイルもそれに応じて更新する必要があります。これにより、新しい依存関係や更新されたバージョン範囲に対応する具体的なパッケージバージョンが確定します。

### どのような時に実行する必要があるか、またはないか
- 必要な場合：
    - pyproject.tomlで依存関係が追加・更新された後。
    - プロジェクトを別の環境に移行するとき、依存関係の一貫性を保証したい場合。
- 必要ない場合：
    - 既にpoetry.lockが最新であり、pyproject.tomlに変更がない場合。
    - 単純なコードの変更や、依存関係に影響を与えないプロジェクトの設定を変更する場合。

:::


## Poetryプロジェクトに指定されたライブラリをインストールする
以下コマンドを実行することで、`pyproject.toml`と`poetry.lock`（あれば）を参照してライブラリのインストールが行われる。
```sh 
poetry install 
```

:::note info
### 依存環境解決のためのPython環境
この`poetry install`での依存関係の解決には、`poetry env info`で`System`の項目に記載されているPython環境が使用される。

```sh 
|*･ω･)っ poetry env info

Virtualenv
Python:         3.11.2
Implementation: CPython
Path:           /Users/Ryku/Documents/sub_work/.venv
Executable:     /Users/Ryku/Documents/sub_work/.venv/bin/python
Valid:          True

System
Platform:   darwin
OS:         posix
Python:     3.11.2
Path:       /Users/Ryku/.pyenv/versions/3.11.2
Executable: /Users/Ryku/.pyenv/versions/3.11.2/bin/python3.11
```

**Systemに記載されているPythonのVersionよりも新しいものをPoetryで構築するPythonのVersionに指定することはできない。**

もし古いPython（例えば3.7等）がSystemに設定されていた場合は、以下のコマンド等を打つことで`System`のPython環境を変更できる。
```sh 
$ poetry env use 3.10.10
```
もちろんここで指定するPython環境はすでにインストールされているのものでないとダメ。
先に`pyenv`を入れて`pyenv install 3.10.10`等を実行した後に上記コマンドを実行して`Poetry`の`System`に設定するのがおすすめ。

:::


## Poetryプロジェクトの仮想環境に入る

```sh
poetry shell
```

画像のようにユーザー名の左側に仮想環境名が表示されていれば成功。`python hoge.py`と実行した際にその仮想環境で実行されるようになっている。
![スクリーンショット 2023-04-27 0.06.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/965436/b0e7935e-e6e5-20a2-cfb2-53e1087d0ff8.png)

:::note info
### Tips of `poetry shell` vs `source`

以下コマンドでもPoetryが作成した仮想環境に入ることができる。`poetry shell`が意図した動作をしない場合は以下のコマンドを推奨。
```sh 
# 直下の.venv環境に入る
source .venv/bin/activate
```

```sh
# ホームディレクトリ下の仮想環境に入る
 source /Users/<any_name>/Library/Caches/pypoetry/virtualenvs/<env_name>/bin/activate
```

### Ask ChatGPT to explain What poetry shell is.
`poetry shell`は内部的に仮想環境のactivateスクリプトを実行しているのですが、それをサブプロセスで実行しているため、呼び出し元のシェルの環境に影響を与えません。ただし、sourceコマンドを使って明示的にactivateスクリプトを実行すると、呼び出し元のシェルの環境に影響を与えます。

poetry shellコマンドを実行すると、Poetryはプロジェクトに関連付けられた仮想環境を見つけます（存在しない場合は作成します）。
次に、Poetryは新しいサブプロセスを起動します。この新しいサブプロセスは、現在のシェルとは別の環境を持っています。
新しいサブプロセス内で、Poetryはactivateスクリプトを実行します。これにより、仮想環境のPythonインタープリタが使用されるようになります。
サブプロセスが終了すると、呼び出し元のシェルは元の状態に戻ります。
この仕組みのために、poetry shellは呼び出し元のシェル環境に影響を与えません。しかし、sourceコマンドを使って明示的にactivateスクリプトを実行すると、呼び出し元のシェル環境に仮想環境のPythonインタープリタへのパスが追加されるため、仮想環境を正しくアクティブにできます。

この問題は、シェルや環境変数の設定に依存することがあります。poetry shellが期待通りに動作しない場合は、sourceコマンドを使って仮想環境をアクティブにすることで、問題を回避できます。

:::

:::note info
### VSCodeに仮想環境を認識させる
`settings.json`に以下の記述を追記します。
プロジェクト直下に`.vscode`ディレクトリを作成し、そのディレクトリ内に以下のファイルをおけば、プロジェクト内でのみ適用させることができます。

```json:settings.json
{
    "python.defaultInterpreterPath": "/Users/<user_name>/Library/Caches/pypoetry/virtualenvs/<env_name>/bin/python"
}
```
:::

## Poetryプロジェクトの仮想環境から抜ける
新しい仮想環境に入りたい時は一回以下コマンドを挟む。
```sh 
deactivate
```

:::note warn
### 仮想環境の出入りをせずに作成したpythonを使うこともできる
`pyproject.toml`ファイルが存在する場所で`poetry env info --path`コマンドを使用すると、作成したpython環境のパスが特定できる。仮に以下のような結果だったと仮定する。

```sh
$ poetry env info --path
/Users/ryku/Library/Caches/pypoetry/virtualenvs/apple-py3.11
```

このとき、以下のように実行すると、どこのディレクトリに居たとしても所望のpython環境を呼び出すことができる。
```sh 
/Users/ryku/Library/Caches/pypoetry/virtualenvs/apple-py3.11/bin/python '実行したいファイル'
```
:::

## Poetryプロジェクトの仮想環境の削除
```sh 
poetry env remove <vertual_env_name>
```

## 作成済み仮想環境一覧

```sh
poetry env list
```