pipを使用した既存環境からPoetryに移行した話し

# はじめに

この記事は JSL (日本システム技研) Advent Calendar 2024 - Qiita 2日目の記事です(カレンダー的には3日目です:sweat_smile:)。

予定ですと[前回](URL "https://qiita.com/katekichi/items/925dcfadd1d926feba3d")の続きで、FAST APIを使った簡易CRMのデータ永続化について書く予定でしたが、環境構築で、開発向け、本番向けと`requirements.txt`を整備しようと思った過程でモダンな`Poetry`に移行したいと思い割り込みで記事にしたいと思った次第です。


移行するにあたって[こちら](URL:"https://tech.dentsusoken.com/entry/2022/08/22/Poetry_%E3%81%AF%E3%81%98%E3%82%81%E3%81%BE%E3%81%97%E3%81%9F_-_%E3%83%81%E3%83%BC%E3%83%A0%E9%96%8B%E7%99%BA%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B_Python_%E3%81%AE%E9%96%8B%E7%99%BA%E7%92%B0%E5%A2%83")の記事を参考にさせて頂きました。

個人的には、開発向け、ステージング向け、本番向けと`requirements.txt`を切り分ける作業が面倒で移行しようと思ったわけですが、上記の記事にあるように`requirements.txt`への記載漏れも良くあるなと思いました。

# 使ってみる
環境：
・macOS 12.6 Apple M1 Pro
・Python 3.12.7 

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

```terminal
$ curl -sSL https://install.python-poetry.org | python3 -
```
上記公式に従ってインストールとPATHの設定をします。

```terminal
$ poetry --version
Poetry (version 1.8.3)
```
インストールの確認。

Poetryは`virtualenv`によって仮想環境の管理を
します。デフォルトだと、Poetryのインストール先配下に
`virtualenvs`フォルダを作って管理しますが`venv`による運用が慣れているため設定を変更してプロジェクト配下に`.venv`フォルダを作成するように設定変更します。

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

# 既存環境の移行

## 現状確認と、既存フォルダをrename

現状の`requirements.txt`は以下の感じです。
```py
annotated-types==0.7.0
anyio==4.6.2.post1
certifi==2024.8.30
click==8.1.7
dnspython==2.7.0
email_validator==2.2.0
fastapi==0.115.5
fastapi-cli==0.0.5
h11==0.14.0
httpcore==1.0.7
httptools==0.6.4
httpx==0.28.0
idna==3.10
itsdangerous==2.2.0
Jinja2==3.1.4
markdown-it-py==3.0.0
MarkupSafe==3.0.2
mdurl==0.1.2
orjson==3.10.12
pydantic==2.10.2
pydantic-extra-types==2.10.0
pydantic-settings==2.6.1
pydantic_core==2.27.1
Pygments==2.18.0
python-dotenv==1.0.1
python-multipart==0.0.18
PyYAML==6.0.2
rich==13.9.4
shellingham==1.5.4
sniffio==1.3.1
starlette==0.41.3
typer==0.14.0
typing_extensions==4.12.2
ujson==5.10.0
uvicorn==0.32.1
uvloop==0.21.0
watchfiles==1.0.0
websockets==14.1
```

念のため既存環境はバックアップしておきます（移行完了後に削除します）。
```terminal
$ cd [プロジェクトフォルダ]
$ mv .venv .venv.old
```

## poetryによる環境構築

既にプロジェクトが存在するので、`poetry new`ではなく、`poetry init`をします。
```terminal
$ poetry init
```
基本的にデフォルトのままとし、`Compatible Python versions [^3.9]:  ^3.12`
のみ設定をしました。

`pyproject.toml`が作成されていることを確認します。

```terminal
$ ls -la pyproject.toml
-rw-r--r--  1 katekichi  staff  270 Dec  3 19:08 pyproject.toml
```

## requirements.txtからpyproject.tomlへの移行について

通常だと`poetry add`でパッケージをインストールしていきますが、既存の`requirements.txt`があるので、これを利用したいと思いました。

参考記事を参考にして、`poetry add $( cat requirements.txt ) --group dev`
として、インストールしました。

```terminal
$ poetry add $( cat requirements.txt ) --group dev
```

完了後に、`poetry show`でインストールした内容を確認できます。

```terminal
$ poetry show                                              
annotated-types      0.7.0       Reusable constraint types to use with typing.Annotated
anyio                4.6.2.post1 High level compatibility layer for multiple asynchronous event loop implementations
certifi              2024.8.30   Python package for providing Mozilla's CA Bundle.
click                8.1.7       Composable command line interface toolkit
dnspython            2.7.0       DNS toolkit
email-validator      2.2.0       A robust email address syntax and deliverability validation library.
fastapi              0.115.5     FastAPI framework, high performance, easy to learn, fast to code, ready for produ...
fastapi-cli          0.0.5       Run and manage FastAPI apps from the command line with FastAPI CLI. 🚀
h11                  0.14.0      A pure-Python, bring-your-own-I/O implementation of HTTP/1.1
httpcore             1.0.7       A minimal low-level HTTP client.
httptools            0.6.4       A collection of framework independent HTTP protocol utils.
httpx                0.28.0      The next generation HTTP client.
idna                 3.10        Internationalized Domain Names in Applications (IDNA)
itsdangerous         2.2.0       Safely pass data to untrusted environments and back.
jinja2               3.1.4       A very fast and expressive template engine.
markdown-it-py       3.0.0       Python port of markdown-it. Markdown parsing, done right!
markupsafe           3.0.2       Safely add untrusted strings to HTML/XML markup.
mdurl                0.1.2       Markdown URL utilities
orjson               3.10.12     Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy
pydantic             2.10.2      Data validation using Python type hints
pydantic-core        2.27.1      Core functionality for Pydantic validation and serialization
pydantic-extra-types 2.10.0      Extra Pydantic types.
pydantic-settings    2.6.1       Settings management using Pydantic
pygments             2.18.0      Pygments is a syntax highlighting package written in Python.
python-dotenv        1.0.1       Read key-value pairs from a .env file and set them as environment variables
python-multipart     0.0.18      A streaming multipart parser for Python
pyyaml               6.0.2       YAML parser and emitter for Python
rich                 13.9.4      Render rich text, tables, progress bars, syntax highlighting, markdown and more t...
shellingham          1.5.4       Tool to Detect Surrounding Shell
sniffio              1.3.1       Sniff out which async library your code is running under
starlette            0.41.3      The little ASGI library that shines.
typer                0.14.0      Typer, build great CLIs. Easy to code. Based on Python type hints.
typing-extensions    4.12.2      Backported and Experimental Type Hints for Python 3.8+
ujson                5.10.0      Ultra fast JSON encoder and decoder for Python
uvicorn              0.32.1      The lightning-fast ASGI server.
uvloop               0.21.0      Fast implementation of asyncio event loop on top of libuv
watchfiles           1.0.0       Simple, modern and high performance file watching and code reload in python.
websockets           14.1        An implementation of the WebSocket Protocol (RFC 6455 & 7692)
```

動作確認して問題無いことを確認
```terminal
$ source .venv/bin/activate
$ uvicorn app.main:app --reload
```

最後にバックアップした既存環境を削除します。
```terminal
$ rm -r .venv.old
```

# まとめ

思いつきでの作業でしたが、30分程度で移行できました。
今回は、ステージング環境や本番環境で実行前の状態での移行だったため
容易な作業でしたが、既に稼働中のアプリケーションについては手順を慎重に吟味する必要があるなと感じました。そのような機会があった場合は、別途記事にしたいと思います！。