pythonのモジュールを必要な物だけに保つ

# pythonのモジュールを必要な物だけに保つ

ローカルじゃ動くのに、サーバ（クラウド）上でモジュールが見つからないとか有りますよね

また、不要になったモジュールが残っていたり


## フォルダー階層

```
.
├── app
│   ├── main.py # pythonのソース
├── requirements  
│   ├── base.in # 実行に必要なもの
│   ├── base.txt
│   ├── dev.in # テストや開発に必要なもの
│   └── dev.txt
└── scripts
    └── pip.sh
```

## requirements/base.in の例
```requirements/base.in
aiosmtplib
alembic
asyncpg
azure-communication-email
azure-functions
azure-identity
azure-storage-blob
chardet
fastapi
fastapi-healthchecks
Jinja2
msgraph-sdk
opencensus-ext-azure
opencensus-ext-fastapi
openpyxl
passlib
Pillow
psycopg2-binary
pydantic
pydantic-core
pydantic-settings
pydantic[email]
python-multipart
pytz
Secweb
sqlalchemy
```

## requirements/dev.in の例
```requirements/dev.in
-r base.in
autoflake
black
freezegun
httpx
isort
pip-compile-multi
pyproject-flake8
pytest
pytest-asyncio
pytest-azurepipelines
pytest-cov
pytest-dotenv
pytest-mock
pytest-postgresql
sqlalchemy-utils
```

## 実行シェルにしておくと便利
```scripts/pip.sh
#!/bin/sh
pip install --upgrade pip # pipをupgradeする
pip install pip-tools # pip-toolsをインストール（requirements/dev.inには入れない）
pip-compile-multi # requirements/*.inからrequirements/*.txtが作られる
pip-sync requirements/dev.txt # 候補に無いものはuninstallされる
```

### dev.txt はこうなる
```requirements/dev.txt
# SHA1:21928a7634f95b9f09819688a328f79d34eee3b5
#
# This file is autogenerated by pip-compile-multi
# To update, run:
#
#    pip-compile-multi
#
-r base.txt
autoflake==2.3.1
    # via -r requirements/dev.in
black==24.10.0
    # via -r requirements/dev.in
build==1.2.2.post1
    # via pip-tools
click==8.1.7
    # via
    #   black
    #   pip-compile-multi
    #   pip-tools
coverage[toml]==7.6.4
    # via pytest-cov
flake8==7.0.0
    # via pyproject-flake8
freezegun==1.5.1
    # via -r requirements/dev.in
importlib-resources==6.4.5
    # via pytest-azurepipelines
iniconfig==2.0.0
    # via pytest
isort==5.13.2
    # via -r requirements/dev.in
mccabe==0.7.0
    # via flake8
mirakuru==2.5.3
    # via pytest-postgresql
mypy-extensions==1.0.0
    # via black
pathspec==0.12.1
    # via black
pip-compile-multi==2.6.4
    # via -r requirements/dev.in
pip-tools==7.4.1
    # via pip-compile-multi
platformdirs==4.3.6
    # via black
pluggy==1.5.0
    # via pytest
port-for==0.7.4
    # via pytest-postgresql
psycopg==3.2.3
    # via pytest-postgresql
pycodestyle==2.11.1
    # via flake8
pyflakes==3.2.0
    # via
    #   autoflake
    #   flake8
pyproject-flake8==7.0.0
    # via -r requirements/dev.in
pyproject-hooks==1.2.0
    # via
    #   build
    #   pip-tools
pytest==8.3.3
    # via
    #   -r requirements/dev.in
    #   pytest-asyncio
    #   pytest-azurepipelines
    #   pytest-cov
    #   pytest-dotenv
    #   pytest-mock
    #   pytest-nunit
    #   pytest-postgresql
pytest-asyncio==0.24.0
    # via -r requirements/dev.in
pytest-azurepipelines==1.0.5
    # via -r requirements/dev.in
pytest-cov==6.0.0
    # via -r requirements/dev.in
pytest-dotenv==0.5.2
    # via -r requirements/dev.in
pytest-mock==3.14.0
    # via -r requirements/dev.in
pytest-nunit==1.0.7
    # via pytest-azurepipelines
pytest-postgresql==6.1.1
    # via -r requirements/dev.in
sqlalchemy-utils==0.41.2
    # via -r requirements/dev.in
toposort==1.10
    # via pip-compile-multi
wheel==0.44.0
    # via pip-tools

# The following packages are considered to be unsafe in a requirements file:
# pip
# setuptools
```