転職黙示録 (5) 意外と使えるPoetry入門 (Poetry + FastAPI)

# Poertry入門

## 概要

　プロジェクトを作ってPoertryの完成度を体感してみる.

## pyenv

### pyenvとは?

 pyenvは複数のPythonインタプリタを管理するツールです.

+ 特定のバージョンのPythonインタプリタのインストール
+ 複数あるバージョンの切り替え
+ プロジェクトごとのPythonバージョンの設定

 などができます.

### pyenvの導入

 ググってください:pray:

### pyenvを使ったPythonの導入

 pyenvが導入できたでしょうか? それでは以下のコマンドを実行してみましょう.

```bash
ls $(pyenv root)
```

　shimsとversionsというフォルダがあります. どちらもまだ空のはずです. また現在のPythonのバージョンを確認してsystemに設定されていることも確認しましょう.

```bash
pyenv version
```

　これはpyenvが管理しているpythonがsystemが提供しているものしかないことを意味します. 実際利用可能なPythonインタプリタを確認するとsystemしかなくその行の初めにアスタリスクが(*)がついています. これが現在の位置でスクリプトなどを実行した時に使われるPythonです. インストールするとここに候補が増えていきます.

```bash
pyenv versions
```
　ではインストール可能なPython環境を調べましょう.

```bash
pyenv install --list
```

　大量のリストが出てきますがgrepなどを駆使して必要なものを探しても良いでしょう. 今回は3.7.4を使うことにしてみます.

```bash
# take a while to install Python 3.7.4
pyenv install 3.7.4
```

 インストールが終了したらversionsサブコマンドなどで3.7.4という行が追加されていることを確認しましょう.

### global vs local

 両者の違いは以下のようになります.

|global|local|
|:----:|:---:|
|システム全体で使われるPython|指定したフォルダ以下で利用されるPython|

　同名のサブコマンドで設定が調べられます.

```bash
pyenv global 
# system
pyenv local
# pyenv: no local version configured for this directory
```

 今回はglobalを変える意味は無いので, localでプロジェクト別にpythonを設定することにしましょう. プロジェクトはpoetryで作りますので後で設定します.

### shimsとは?

　一般にshimはAPI間の差異を一種のプログラムを指す言葉のようです. ここでの差異はCLIです. pyenvでは本来はシステムのpythonが呼び出される時に適切なpythonを呼び出す必要があります. pyenvはshimsというファイルをコマンドのサーチパスの先頭に追加します.

```bash
echo $PATH
# $(pyenv root)/shims
```

　shimsには指定されたpythonインタプリタやpipといった必要な実行ファイルが含まれています. ここで重要なのですが, shims以下に保存されているコマンドが直接呼び出されるわけでは無いのです. このコマンドpyenvに渡されて適切なバージョニングなどが行われるようです(詳しくは自己テストをやってみてください).

```bash
python local 3.7.4
which python3.7
# $(pyenv root)/shims/python3.7
```

 こうやってバージョンごとのCLIの差をPython限定ですが吸収しているからshimsというフォルダ名になっているようです.

### 自己テスト

1. 3.6.9をインストールして3.7.4とは別のローカル環境を構築して, 2つのバージョンにsite-packagesが別々に存在することを確かめよう.

2. 片方バージョンでpipを使ってpipenvを導入し, 両方で実行して見よう.

### 解説

　shims以下のコマンドがpyenvに渡されるといことを説明しました. 1では比較のために別バージョンのpythonを入れでそれぞれがpipコマンドを持ち, また別の環境(site-packages)を持つことを確かめます. 2でpipenvを導入します.

```bash
pyenv local
# 3.6.9
pip install pipenv
```

　pipenvはどちらのバージョンでも実行できます(つまりwhichでは見分けがつかない). それはshims以下に置かれているからです. そこでpipenvにはinstallコマンドがあるので, パッケージを追加できるか試してみましょう. pipenvが導入されていない3.7.4でこれを実行してみましょう.

```bash
pipenv install numpy
pyenv: pipenv: command not found

The `pipenv' command exists in these Python versions:
  3.6.9
```

　現在のローカル環境ではpipenvは存在しないとエラー・メッセージが出ます. 少しshimsの動きが分かったでしょうか?

## Poetry

### Poetryの導入

[公式のインストールガイド](https://poetry.eustace.io/docs/#installation)を参考にしてください.

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

```bash
poetry new --src test
```

 ここでpyenvで導入した3.7.4をプロジェクトのpythonにしておきましょう.

```bash
cd test
pyenv local 3.7.4
```

### リポジトリの検索

 FastAPIで開発するにはfastapiとuvicornというパッケージが必要です.

```bash
poetry search fastapi
poetry search uvicorn
```

　両方ちゃんと認識されています.

### 依存パッケージの追加とインストール

　addサブコマンドで行います.

```bash
poetry add fastapi
poetry add uvicorn
```
 pyproject.tomlにパッケージが追加されています. GitHubなどでプロジェクトを管理するなら, クローンしてインストールサブコマンドを実行すれば良いです.

```bash
cd project_file
poetry install
```

 簡単ですね.

### ソースコード

 とりあえず公式の[Example](https://fastapi.tiangolo.com/#example)をやってみましょう. src以下にtestというフォルダがあるはずなのでここに以下のこーどをコピーします.

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

app = FastAPI()


@app.get("/")
def read_root():
    return {"Hello": "World"}


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

### 仮想環境の確認と

　さて実行したいわけですが, uvicornというコマンドで実行することになっています. addサブコマンドでインストールされたパッケージはどこへいったのでしょうか? poetryはaddサブコマンドを実行すると同時にインストールも行います. この時点で仮想環境も構築されます. この中に依存パッケージが入っています.

```bash
poetry config --list
```

　仮想環境を立ち上げるにはshellサブコマンドを実行します.

```bash
poetry shell
```

### いよいよ実行する.

 後は簡単です. 立ち上がったbashから以下のコマンドを実行するだけです.

```bash
uvicorn src.test.main:app --reload
```

 サーバーが起動するので指定されたURLを開くと{"Hello":"World"}と表示されているはずです.

## 補足

### virtualenvの起動

```bash
poetry config --list
```

　を実行したsettings.virtualenvs.pathに設定されているフォルダにtest-py3.7というのがあると思います. これをsourceコマンドの引数として渡すとシェルが起動します. この仮想シェルのなかでuvicornを実行しているわけです.

```bash
source path/to/virtualenvs/test-py3.7/bin/active
```

 実際にこのコマンドを起動したらちゃんとuvicornは存在しています.

## まとめと課題

　Poetryを使って非常に簡単にAPIサーバーが立てられそうな気になってきました. とりあえずこれぐらいのことなら特にエラーなどは起こりませんでした.

　ただ現状では仮想環境の管理がよく分かりません. 使い勝手が悪いというわけではないんですが, 別の環境を使いたい(例えばバージョンを変える)などの場合は不安です. また調べて追記したいと思います.. まぁuvicornがいるのでコマンドライン・ツールならこのような面倒なことは必要ないようですが.



## 参考
1. [PoetryでPython CLIツールを簡単にPyPiに登録する](https://rcmdnk.com/blog/2019/02/04/computer-python/)
2. [Poetryを使ったPythonパッケージ開発からPyPI公開まで]()http://kk6.hateblo.jp/entry/2018/12/20/124151
3. [fastapi-realworld-example-app](https://github.com/nsidnev/fastapi-realworld-example-app)