Python - dotenv 教學
在開發 Python 應用程式時,我們經常需要處理一些敏感資訊或設定值,例如 API 金鑰、資料庫密碼、或是不同部署環境(開發、測試、生產)的特定設定。將這些資訊直接寫在程式碼中不僅不安全,也難以管理。
這時候,python-dotenv
這個函式庫就能派上用場了!
什麼是 python-dotenv
?
python-dotenv
是一個簡單易用的 Python 函式庫,它可以幫助我們從一個名為 .env
的檔案中讀取鍵值對 (key-value pairs),並將它們載入到環境變數 (environment variables) 中。這樣一來,我們就可以將設定與程式碼分離,讓專案更加安全且易於維護。
為什麼要使用 dotenv
?
- 安全性:避免將 API 金鑰、密碼等敏感資訊直接寫入程式碼,降低外洩風險。
- 設定管理:方便管理不同環境(開發、測試、生產)的設定,只需修改
.env
檔案即可。 - 程式碼整潔:將設定值與主要邏輯分離,讓程式碼更易讀、易懂。
- 協作方便:團隊成員可以各自維護自己的
.env
檔案,而不需要將敏感資訊提交到版本控制系統 (如 Git)。
安裝 python-dotenv
安裝非常簡單,只需要使用 pip
:1
pip install python-dotenv
如何使用?
建立 .env
檔案
首先,在你的專案根目錄下建立一個名為 .env
的檔案。這個檔案的格式很簡單,就是一行一個鍵值對,用 =
連接:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16# .env 檔案範例
# 資料庫設定
DB_HOST=localhost
DB_PORT=5432
DB_USER=myuser
DB_PASSWORD=mypassword
# API 金鑰
API_KEY=your_secret_api_key_here
# 其他設定
DEBUG=True
APP_NAME="My Awesome App"
APP_HOST=localhost
APP_PORT=8000
BASE_URL=http://${APP_HOST}:${APP_PORT}/api # 使用了變數內插,後面會詳細說明
注意:
- # 開頭的行是註解。
- 不需要用引號將值包起來,除非值本身包含空格或特殊字元。
- 鍵 (key) 通常使用大寫字母和底線。
在 Python 程式碼中載入環境變數
接著,在你的 Python 程式碼中,匯入 load_dotenv
函數並執行它。通常建議在程式的入口點(例如 main.py
或 app.py
)的開頭就載入:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47import os
# 建議同時匯入 find_dotenv 來更可靠地定位 .env 檔案
from dotenv import load_dotenv, find_dotenv
# 載入 .env 檔案中的環境變數
# 使用 find_dotenv() 會自動從目前腳本位置向上搜尋 .env 檔案,更為穩健
# 如果沒找到檔案,它預設不會報錯
load_dotenv(find_dotenv())
# 現在可以使用 os.getenv() 來取得環境變數
# 注意:os.getenv() 讀取的所有值預設都是字串!
db_host = os.getenv("DB_HOST")
db_user = os.getenv("DB_USER")
db_port_str = os.getenv("DB_PORT") # 讀取到的是字串 "5432"
api_key = os.getenv("API_KEY")
debug_mode_str = os.getenv("DEBUG") # 讀取到的是字串 "True"
app_port_str = os.getenv("APP_PORT") # 讀取到的是字串 "8000"
print(f"資料庫主機: {db_host}")
print(f"資料庫使用者: {db_user}")
print(f"API 金鑰 (前幾個字元): {api_key[:5]}...") # 避免完整印出金鑰
print(f"讀取到的除錯模式 (字串): {debug_mode_str}")
print(f"讀取到的資料庫埠號 (字串): {db_port_str}")
# 對於非字串類型,需要進行手動轉換
# 將讀取到的字串轉換為布林值
is_debug = debug_mode_str.lower() == 'true' if debug_mode_str else False
print(f"除錯模式 (布林值): {is_debug}")
# 將讀取到的字串轉換為整數
try:
db_port = int(db_port_str) if db_port_str else None
app_port = int(app_port_str) if app_port_str else 8000 # 或者提供數字預設值
print(f"資料庫埠號 (整數): {db_port}")
print(f"應用程式埠號 (整數): {app_port}")
except ValueError:
print("錯誤:埠號設定不是有效的數字!")
# 在實際應用中可能需要更完善的錯誤處理
# 如果環境變數不存在,os.getenv() 預設會回傳 None
non_existent_var = os.getenv("NON_EXISTENT_VAR")
print(f"不存在的變數: {non_existent_var}")
# 也可以提供預設值給 os.getenv(),如果變數不存在或為空,會使用預設值
default_var = os.getenv("ANOTHER_NON_EXISTENT_VAR", "預設值")
print(f"有預設值的變數: {default_var}")
進階用法
除了基本載入功能,python-dotenv
還提供了一些進階選項:
指定
.env
檔案路徑 (dotenv_path):
如果你不想使用預設的 .env 檔名或路徑,可以明確指定:1
2# 假設你的設定檔在 'config/.env_prod'
load_dotenv(dotenv_path='config/.env_prod')覆蓋現有環境變數 (override):
預設情況下,load_dotenv()
不會覆蓋系統中已存在的同名環境變數。若希望.env
檔案優先,設定override=True
:1
2# 即使系統已有 DEBUG 變數,也會被 .env 中的值覆蓋
load_dotenv(override=True)變數內插 (Interpolation):
.env 檔案支援變數引用,可以使用${VAR_NAME}
語法:1
2
3
4# .env 檔案中
APP_HOST=localhost
APP_PORT=8000
BASE_URL=http://${APP_HOST}:${APP_PORT}/api載入後,
os.getenv("BASE_URL")
會得到 http://localhost:8000/api。自動尋找
.env
檔案 (find_dotenv
):
正如我們先前在基本用法中推薦的,find_dotenv()
是一個輔助函數,它會從執行 Python 腳本的目錄開始,逐層向上查找,直到找到指定的檔案(預設是.env
)或到達根目錄為止。這使得即使你的腳本是從專案的不同子目錄執行的,load_dotenv(find_dotenv())
也能正確找到位於專案根目錄的.env
檔案,因此更加穩健。1
2
3
4
5
6# 回顧基本用法中的推薦寫法:
from dotenv import load_dotenv, find_dotenv
load_dotenv(find_dotenv())
# 你也可以傳遞參數給 find_dotenv,例如指定不同的檔名或設定找不到時是否報錯:
# load_dotenv(find_dotenv(filename='.env.prod', raise_error_if_not_found=True))讀取變數到字典 (dotenv_values):
如果你不想修改os.environ
,只想讀取.env
內容作為字典:1
2
3
4from dotenv import dotenv_values
config = dotenv_values(".env") # 回傳一個字典
db_host = config.get("DB_HOST")
print(f"從字典讀取 DB Host: {db_host}")
將 .env 加入 .gitignore
非常重要! 為了避免將敏感資訊提交到版本控制系統 (例如 Git),你應該將 .env
檔案加入到專案的 .gitignore
檔案中。在你的 .gitignore
檔案中加入一行:1
2
3
4
5
6
7
8# .gitignore
# 忽略 dotenv 環境檔案
.env
# 其他需要忽略的檔案或目錄...
__pycache__/
*.pyc
這樣一來,當你使用 Git 進行版本控制時,.env
檔案就不會被追蹤或提交了。
總結
python-dotenv
是一個非常實用且靈活的工具,可以幫助開發者更安全、更方便地管理 Python 專案中的設定和敏感資訊。透過將設定與程式碼分離,並搭配版本控制系統的忽略清單,可以有效提升專案的品質與安全性。下次開發 Python 專案時,試試看 dotenv
吧!