在開發專案時,常常有一種需求是配置隨環境而變,例如資料庫的連線字串:

  • 在開發環境是 postgresql://localhost:5432/mocha
  • 在測試環境是 postgresql://dbadmin:dbpw@localhost/mocha
  • 在正式環境是 postgresql://ap:[email protected]:5432/mocha

又或者其它第三方服務的環境或帳密不同,例如某個外部檔案儲存服務也有提供測試環境給我們用,在我們的開發環境與測試環境:

  • 檔案儲存服務的位址是 192.168.101.234:5000
  • 帳號是 yc
  • 密碼是 bepoliteto

在我們的正式環境:

  • 檔案儲存服務的位址是 192.168.102.234:5000
  • 帳號是 yc
  • 密碼是 begentleto

像這類會隨環境而變的配置,當然不能寫死在程式碼內,一般約定成俗的慣例是把它們寫入檔名為 .env 的配置文件內,一個典型的 .env 大概像這樣:

DATABASE_URL = "postgresql://postgres:mysecretpassword@localhost:5432/mocha"

FILE_SERVICE_ADDRESS = "192.168.101.234:5000"
FILE_SERVICE_ACCOUNT = "yc"
FILE_SERVICE_PASSWORD = "bepoliteto"

這份 .env 檔案,慣例上不會進板控,而是手動拷貝到各個環境的專案資料夾內。

不論是何種語言大都有專門載入 .env 檔案的套件,它會幫我們讀取 .env 的條目鍵值,並存入相對的程式變數(或常數)內。在 Python 方面就是 python-dotenv

python-dotenv

python-dotenv 載入 .env 檔案的條目後,會把條目們存入 OS 的環境變數中,所以我們可以透過 os.getenv() 來取得這些連線字串或帳密,最簡單的範例如下:

from dotenv import load_dotenv

load_dotenv(dotenv_path='.env')  # take environment variables from .env.

# Code of your application, which uses environment variables (e.g. from `os.environ` or
# `os.getenv`) as if they came from the actual environment.
print(os.getenv(key='DATABASE_URL'))

把上面這份 Python 腳本跑起來就會得到前面我們定義的資料庫連線字串。

如果在執行 Python 腳本之前,我們就已經有了一個同樣名為 DATABASE_URL 的環境變數,那麼 python-dotenv 不會把它蓋掉,以原有的環境變數優先存在。

如果不想以環境變數的形式取用 .env 條目,還有另一個 dotenv_values() 方法,它會把 .env 條目存成一份 dict 物件,範例如下:

from dotenv import dotenv_values

config = dotenv_values(dotenv_path='.env')  # config = {"USER": "foo", "EMAIL": "[email protected]"}

python-dotenv 本身是滿單純也滿簡單的套件,用法就上面兩種,希望這篇短文對也在跑多環境專案的你有幫助。