Python環境構築(pyenv+poetry+pipx)

# What's this?
macbookのPython環境を

- pyenv
- poetry
- pipx

で構築したので, そのメモです.
環境は**mac OS 10.14.6 Mojave**です.
この記事はintel macでの環境構築の話です.
M1 macで同じ手順で環境構築できるかは知りません(持ってないので).
デフォルトシェルがbashからzshに変わった等の違いはありますが, intel macであれば2021年現在も同じように環境構築可能です.
homebrewはすでに入っている前提で進めます.
(homebrewを入れてない人は[Homebrew公式](https://brew.sh/index_ja)を参考にして入れてください)
適宜更新していくと思います.

# Python3のインストール
homebrewでsystemのpython3をインストールします.
すでに入れてる人は飛ばしてください.
また, 「どうせ後でpyenv入れるんやろ. pyenvで入れるからええわ」って人も飛ばしてください.
systemにpython3をインストールするのは僕の趣味です.(~~あと, なんかよくわかんないけど, pyenv上のpythonでnumpy,scipyをmklとリンクさせようとすると失敗するから...~~何とかなりました.詳しくは[ここ](https://qiita.com/yano404/items/b78503749c2e45b4b638))

```
$ brew install python
```

(2020.07.12追記)
homebrewから`python`フォーミュラが消えました.
`python@3.7`か`python@3.8`の好きな方を選んでください.
(というかここまできたらもうシステムにインストールせんでもええのでは...)

# pyenvのインストール
[公式](https://github.com/pyenv/pyenv#installation)に従って `pyenv` を入れます.
`brew install pyenv` が楽なのだろうけど, `PYENV_ROOT=/usr/local/var/pyenv` となるのがあまり好きではない(完全に趣味です.Linux環境となるべく同じにしたいという思いもある.)ので, `git` で入れます( `brew install pyenv` でも全然問題ないです).

```
$ git clone https://github.com/pyenv/pyenv.git ~/.pyenv
``` 

でインストールした後, `PATH` を通す & `pyenv init` を実行するように`.bash_profile`を編集します.

```
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
$ echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n  eval "$(pyenv init -)"\nfi' >> ~/.bash_profile
```

シェルを再起動すれば, `pyenv` が使えるようになります.

systemにpython3をインストールしてない人はここで `pyenv install 3.7.6`, `pyenv global 3.7.6` をするなりしてください.

`pyenv install` が失敗する場合は, https://developer.apple.com/download/more/?=command%20line%20tools から最新のcommandlinetoolsをインストールすると上手くいくかも.

# poetryのインストール
[公式](https://github.com/python-poetry/poetry#installation)に従います.

```
$ curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python3
```

また自分の趣味ですが, プロジェクトのディレクトリに `.venv` を作るようにするために

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

を実行します.
この辺りの設定は

```
$ poetry config --list
```

で見ることができます.

# pipxのインストール
「そもそもpipxって何なん?」って人向けにざっくり説明すると...

>
pipでインストールするアプリケーション(コマンド)あるやん(`sphinx-quickstart`とか).
そういうやつってだいたいどの仮想環境でも使うやん.
やけど仮想環境全てにインストールするの面倒やん.
そこで, そういうpipで入れるアプリケーション(コマンド)をグローバルに使えるようにするやつ

です.
公式は[ここ](https://github.com/pipxproject/pipx).

そういうのいらんわって人は無視して次に進んでください.


homebrewでpythonをインストールした人は

```
$ brew install pipx
$ pipx ensurepath
```

pyenvで入れたpythonをglobalにしてる人は

```
$ python3 -m pip install --user pipx
$ python3 -m pipx ensurepath
```

tab補完を有効にするために次を `.bash_profile` に追加.

```
eval "$(register-python-argcomplete pipx)"
```

これで一通り終了です.
お疲れ様でした.

# poetryで環境をつくる
poetryで環境を作るときの方法は`poetry new`と`poetry init`の2つあって, ざっくり説明すると

- `poetry new my-package`
 - ディレクトリを作って, その下にpackageの雛形を作ります.
 - ディレクトリ構造はこうなる

```
my-package
├── pyproject.toml
├── README.rst
├── my_package
│   └── __init__.py
└── tests
    ├── __init__.py
    └── test_my_package.py
```

- `poetry init`
 - 質問に答えて, コマンドを実行したディレクトリに`pyproject.toml`を作成する.

パッケージを作る場合は`poetry new <my-package>`, そうでない場合は`poetry init`という認識で良いと思います.

多分後者の場合が多いのでここでは`poetry init`を使って環境をつくります.

まず, プロジェクトで使用するpythonをpyenvでインストールします.
ここでは`3.7.4`を使うとします.

```
$ pyenv install 3.7.4
```

プロジェクト用のディレクトリを作成する.

```
$ mkdir /foo/bar/project
```

`pyenv local`で使用するpythonのバージョンを指定した後, `poetry init`.

```
$ cd /foo/bar/project
$ pyenv local 3.7.4
$ poetry init
(聞かれたことに対して答えるとpyproject.tomlが生成される)
(質問を無視して後でpyproject.tomlを編集してもよい)
(そもそも自分でpyproject.tomlを作ってもよい)
```

`poetry install`で`pyproject.toml`に書かれた通りにパッケージをインストールできます.

```
$ poetry install
(これでpyproject.tomlに書いたパッケージがインストールされる)
(この時点で`.venv`も作られる)
```

`poetry add <package>`でもパッケージを追加することができます.

poetryの使い方について, 詳しくは[公式のドキュメント](https://python-poetry.org/docs/cli/)を見て下さい.

最初に`poetry add`や`poetry install`を使用したときに仮想環境(`.venv`)は自動で作成されますが, その前に `python -m venv .venv` などとして仮想環境を作ってもよいです.
そんな必要あるのと思うかもしれませんが, `pip.conf` を必要とする時にはこうするしかないっぽいので(これ以外の方法を今のところ僕は知りません).
`pip.conf` は `.venv` 以下において下さい(`.venv/pip.conf`となる).
ちなみに, 僕の場合, systemのpython3のpip.conf(`$HOME/.pip/pip.conf`)が

```
[install]
no-binary = numpy,scipy

[wheel]
no-binary = numpy,scipy
```

となっており, 何もしないとこの影響を受けてしまいます.
なので, `numpy, scipy`を使うときは, `.venv/pip.conf`を以下の内容でわざわざ作ってます.

```
[install]
no-binary = 

[wheel]
no-binary = 
```

mklの関係で工夫しないと`numpy, scipy`のbuild失敗するんでこうしてます(~~このあたりは後で記事にします~~記事にしました→[pyenv+poetry環境下のnumpy,scipyでmklを使いたい](https://qiita.com/yano404/items/b78503749c2e45b4b638)).

# (pipx使用例)pipxでsphinxをインストール
`pipx` については使用例を見てもらった方が良いと思うんで, `pipx`を利用して`sphinx`をインストールする手順を紹介します.
前述の通り`sphinx`を全ての仮想環境に入れるの面倒(というか絶対やらない)なので, `pipx`の出番です.

```
$ pipx install sphinx
```

`sphinx_rtd_theme`や`sphinxcontrib-blockdiag`を使いたいときは,

```
$ pipx inject sphinx sphinx_rtd_theme
$ pipx inject sphinx sphinxcontrib-blockdiag
```

とすればよいです.


# 最後に
今までは`pipenv`を使っていたけど, `pipenv`に比べて`poetry`はpackageのインストールが速くてよいですね.
ただ, あまりパッケージ作ることないので, `poetry` である必要があるかと言われるとそうでもない.
他に良さそうなのが出てきたらまた乗り換えるかも(ずっとこれ繰り返してる...ゴールはあるんでしょうか)

# 参考
- [pyenv. GitHub.](https://github.com/pyenv/pyenv)
- [poetry. GitHub.](https://github.com/python-poetry/poetry)
- [pipx. GitHub.](https://github.com/pipxproject/pipx)
- [poetry公式ドキュメント](https://python-poetry.org/docs/cli/)
- [pip User Guide](https://pip.pypa.io/en/stable/user_guide/#config-file)
- ["pyexpat が原因で pyenv install が出来ない解決方法". Qiita.](https://qiita.com/karon9/items/875b8a0053fa1c685386)
- ["ライブラリ： Poetry". Life with python.](https://www.lifewithpython.com/2018/12/poetry.html)
- ["My Python Development Environment, 2020 Edition".Jacob Kaplan Moss.](https://jacobian.org/2019/nov/11/python-environment-2020/)