Pythonのrequirements.txtをなるべくちゃんとする

# 概要

Pythonをいじっていたら、`requirements.txt`に出くわすことがある。

（ホントかよ？　みんなどうやってこういうの覚えるんだ？）

## requirements.txt
requirements.txtには、Pythonプロジェクトで必要なパッケージとそのバージョンをリスト化したテキストファイルが記述されている。

例えば

```
fastapi==0.70.0
uvicorn==0.15.0
lanarky==0.8.4
```

といったようなものだ。

このリストがあれば、必要なパッケージをこういうコマンド一つでインストールできる。


```
pip install -r requirements.txt
```

## 今使っているパッケージのバージョンの確認
今どのバージョンを使用しているかは、

```
pip freeze > requirements.txt
```

で知ることができる。

ただし、依存パッケージも含まれていてきれいではない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439672/ab151c37-a39f-b4d3-7d14-cebda82bd758.png)

目視で書き写す必要があるが、これを、なるべくラクにやりたいので、方法を模索している。

# 背景

俺公爵は趣味からPythonを触り始め、あまり上手なPythonの環境構築がド下手だったので（変な日本語）、いわれるがままにいろいろやろうとしてボタンを押しまくっていた結果、**いつの間にかパソコンにはPython3.7、Python3.8、Python3.9、Python3.10が混在していた**。


さらにそれらに別々によくわからんままにいろんなパッケージを`pip install`だかしてあれがないこれが欲しいこれはなんだ何がpipだふざけるなとキレ散らかしていた結果、ひどい目にあったわけである。

その時のことは……。
まあ、機会があったら別で語ることにしよう。

ともかく、なんか強いエンジニアが当たり前のように`venv`を使っていて、当たり前のように`requirements.txt`とかゆう謎のテキストファイルを置いており、「へーすごいっすね」と相槌を打っていたらなんか便利なツールを作ったから試してみてくれと言われ、`venv`とゆう本当ではない世界（仮想環境）に連れてこられてしまった。

最初は抵抗があったが、慣れてみるとまあ仮想の世界も悪くはない。
今では肉体も電子化し、猫を除いては居住をメタバースに移し、オンスクリーン キーボードでこの記事を書いている。

仮想環境であれば、「テストコードを動かしたいが、どーしても古いバージョンのパッケージを使わざるを得ない」というときに、そのバージョンを指定してやるだけで済む。
「そうだPython3.9にはあえて古いパッケージを入れておいたんだった。Python3.9に切り替えよう……」なんてことはしなくてもよいのだ。

# pip-toolsを使用する
`pip-tools`を使用する。

```
pip install pip-tools
```

で`pip-tools`をインストールする。

# 手順

1. pip-toolsをインストールする。
1. もしすでにrequirements.txtがあれば、requirements.inというファイルを新規作成し、既存のrequirements.txtに書いておいたものを記述する。
バージョン指定がいらない場合はバージョンを除いて記述する（最新のものになる）。
1. 以下のコマンドを使用して自動的にrequirements.txtを更新してもらう。

```
pip-compile requirements.in --strip-extras
```

requirements.txtにはたくさん記述ができるが、この中から「via -r requirements.in」と書いてあるのを拾ってくればよさそうだ。requirements.inに反映できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439672/f315d36f-3b99-f2bf-17f4-7b20177acd75.png)

結局目視になるのか……。
いや、しかし、ここからはChatGPTにでも任せればいいだろう。
この手の作業は幻覚がほぼなく、結構上手だ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439672/d251b26c-6323-0a90-9dcb-e34b4e109c9b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439672/952ee431-10e6-4932-4765-b67396d06a2a.png)

## 追記：requirements.txtはすべて記述してあるものを取っておくのがよさそう

`requirements.in`は、pip-toolsで出してもらったやつをピックアップしたもので良さそうなのだけれど、`requirements.txt`はこのpip-toolsで得られたものすべてをそのまま記述しておいたほうがよさそうである。

これにより再現性の高い環境構築ができそうだ。

[Python Packaging User Guide](https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/)

## 追記２：仮想環境のとき

Dockerや、venvなど、仮想環境で動かしているときはその仮想環境内で上記の作業を行うとよさそうだ。

### TIPS：メモ
pip-toolsのせいではないのだが、依存関係の抱き合わせが悪かったので、numpyパッケージがこんがらがってしまってプログラムの実行に失敗するようになってしまった。

もともとの奴もとっておいて、失敗したパッケージがあったらrequirements.inではなくtxtのほうに付け足し、バージョン指定を削除し、改めてやってもらったらなんとかなった。

具体的な手順としては、numpyまではいらなくなっていたので、削除すると、今度は引きずられてpandasがなくなったので、pandasを追加……というような感じに詰まったやつを1個ずつ解決していった。

# 備考

ほかにも、パッケージ管理の方法としてはPoetryやPipenvやCondaやHatchなどがあるようだ。

# 参考
https://www.switch-science.com/blogs/magazine/20240410-techblog

https://qiita.com/ryu22e/items/ad3f8f3df30886d23661


※本記事はQmonus Value Streamの投稿キャンペーン記事です。

https://qiita.com/official-events/3648bc4e6cedb674491c