Python でも dotenv_flow を使って .env, .env.dev, .env.prod を使い分けて管理する
概要
Next.js を一度触ると .env, .env.dev, .env.prod でそれぞれの環境の環境変数を自動で使い分けられる便利さを痛感しました。
そこで Python でも同じようなことをできないか調べたところ dotenv_flow という OSS ライブラリを使えば可能なことがわかったのでこちらにまとめておきます。
背景
環境変数として管理したいものは以下の2つなどがあるかなと思います。
- 秘匿にするもの
-
Dev,Prodなど環境で変わるもの
例えば以下の例では
-
Dev,ProdでENDPOINT,BASE_URLが変わる。 -
API_KEYは秘匿にしたいので Git でバージョン管理しない
となっております。
ENDPOINT=https://xxx.dev.com
BASE_URL=https://abc.mykinso.com
ENDPOINT=https://yyy.prod.com
BASE_URL=https://abc.mykinso.com
API_KEY=abcdefghijklmn
このように分けて環境変数を管理している場合 Web フレームワークの1つである Next.js では .env と .env.dev あるいは .env と .env.prod を自動でマージしてくれます。
Next.js での開発時、この機能が非常に便利だったため Python でもアプリやサービスの実装時に同じことができないかなと調べてみたら dotenv_flow を用いることで実現できそうでした。
上記のサイトの説明でも
This is the python version of Node's dotenv-flow.
と Node の dotenv-flow ライブラリに影響を受けていることが明記されていますね。
方法
まず dotenv-flow を pip や uv などのライブラリー管理ソフトでインストールしてください。
pip install dotenv-flow
次にコードの .env や .env.dev の情報を読み込みたい箇所で dotenv_flow 関数を実行します。
例えば .env と .env.dev を読み込ませたい場合は以下のように指定します。
:bulb: .env.xxx の xxx の部分を1つ目の引数に入れます
import os
from dotenv_flow import dotenv_flow
dotenv_flow("dev")
endpoint = os.environ.get("ENDPOINT")
base_url = os.environ.get("BASE_URL")
api_key = os.environ.get("API_KEY")
print(f"{endpoint=}")
print(f"{base_url=}")
print(f"{api_key=}")
上記のコードを dotenv_flow を実行した場合とコメントアウトして実行しなかった場合で結果を比べてみます。
> python tutorial.py
endpoint='https://xxx.dev.com'
base_url='https://abc.mykinso.com'
api_key='abcdefghijklmn'
> python tutorial.py
endpoint='https://yyy.prod.com'
base_url='https://abc.mykinso.com'
api_key='abcdefghijklmn'
dotenv_flow を実行しなかった場合 (何も読み込まれない)
> python tutorial.py
endpoint=None
base_url=None
api_key=None
.env, .env.dev, .env.prod の環境変数がマージされて読み込まれていますね!
なお、 .env, .env.dev の両方で同じ変数が記載されていて上書きしたい場合は2つ目の引数として override=True を指定してください。私はこれに気づかず全然上書きされないな〜としばらく悩んでしまいました。
💡 読み込む順番は .env.XXX, .env で最後に .env が読み込まれ優先されます
さらに dotenv_flow(dev) の引数 dev の部分を変数にし自動で dev, prod を切り替えるようにすれば自動で環境ごとの環境変数を切り替えることができます。
import os
from dotenv_flow import dotenv_flow
env = os.environ.get("env") # 現在の環境を調べて "dev" か "prod" をアサインするように実装する
dotenv_flow(env)
endpoint = os.environ.get("ENDPOINT") # .env.dev の情報が読み込まれている
# ...skipping
これで、環境によって自動で環境変数を変えたり、秘匿する環境変数はローカルで保存しつつチームで共有すべき情報は Git でバージョン管理することができました。
💡 まとめ
-
dotenv-flowを用いることで.env.devと.envなどの2つの環境変数を定義しているファイルを読み込むことができました
皆様の参考になれば幸いです。
Discussion