🐡

Python でも dotenv_flow を使って .env, .env.dev, .env.prod を使い分けて管理する

2024/10/17に公開

概要

Next.js を一度触ると .env, .env.dev, .env.prod でそれぞれの環境の環境変数を自動で使い分けられる便利さを痛感しました。
そこで Python でも同じようなことをできないか調べたところ dotenv_flow という OSS ライブラリを使えば可能なことがわかったのでこちらにまとめておきます。

背景

環境変数として管理したいものは以下の2つなどがあるかなと思います。

  • 秘匿にするもの
  • Dev, Prod など環境で変わるもの

例えば以下の例では

  • Dev, ProdENDPOINT, BASE_URL が変わる。
  • API_KEY は秘匿にしたいので Git でバージョン管理しない

となっております。

.env.dev
ENDPOINT=https://xxx.dev.com
BASE_URL=https://abc.mykinso.com
.env.prod
ENDPOINT=https://yyy.prod.com
BASE_URL=https://abc.mykinso.com
.env
API_KEY=abcdefghijklmn

このように分けて環境変数を管理している場合 Web フレームワークの1つである Next.js では .env.env.dev あるいは .env.env.prod を自動でマージしてくれます。

Next.js での開発時、この機能が非常に便利だったため Python でもアプリやサービスの実装時に同じことができないかなと調べてみたら dotenv_flow を用いることで実現できそうでした。

https://pypi.org/project/dotenv-flow/

上記のサイトの説明でも

This is the python version of Node's dotenv-flow.

Nodedotenv-flow ライブラリに影響を受けていることが明記されていますね。

方法

まず dotenv-flowpipuv などのライブラリー管理ソフトでインストールしてください。

pip install dotenv-flow

次にコードの .env.env.dev の情報を読み込みたい箇所で dotenv_flow 関数を実行します。

例えば .env.env.dev を読み込ませたい場合は以下のように指定します。
:bulb: .env.xxxxxx の部分を1つ目の引数に入れます

tutorial.py
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 を実行した場合とコメントアウトして実行しなかった場合で結果を比べてみます。

dotenv_flow を dev にして実行した場合
> python tutorial.py            
endpoint='https://xxx.dev.com'
base_url='https://abc.mykinso.com'
api_key='abcdefghijklmn'
dotenv_flow を prod にして実行した場合
> python tutorial.py            
endpoint='https://yyy.prod.com'
base_url='https://abc.mykinso.com'
api_key='abcdefghijklmn'

dotenv_flow を実行しなかった場合 (何も読み込まれない)

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つの環境変数を定義しているファイルを読み込むことができました

皆様の参考になれば幸いです。

Cykinso's Tech Blog

Discussion