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