èšå®ç®¡çããã£ãšæ¥œã«ãå®å šã« âš
Python ã¢ããªã±ãŒã·ã§ã³ãéçºããŠãããšãAPI ããŒãããŒã¿ããŒã¹èªèšŒæ å ±ãå€éšãµãŒãã¹ã® URL ãªã©ãããŸããŸãªãèšå®å€ããæ±ãå¿ èŠããããŸãããããã®æ å ±ãçŽæ¥ã³ãŒãã«æžã蟌ãã§ããŸããšãã»ãã¥ãªãã£ãªã¹ã¯ãé«ãŸãã ãã§ãªããéçºç°å¢ãšæ¬çªç°å¢ã§èšå®ãåãæ¿ããã®ã倧å€ã«ãªããŸãã
ããã§ç»å Žããã®ã python-dotenv ã©ã€ãã©ãªã§ãïŒ ð ãã®ã©ã€ãã©ãªã䜿ããšã.env
ãšããç¹å¥ãªãã¡ã€ã«ã«èšå®å€ãèšè¿°ããããã Python ã¹ã¯ãªããããç°¡åã«èªã¿èŸŒãããšãã§ããŸããããã«ãããã³ãŒããšèšå®å€ãåé¢ããå®å
šãã€å¹ççã«ã¢ããªã±ãŒã·ã§ã³ã管çã§ããããã«ãªããŸãã
ãã®èšäºã§ã¯ãpython-dotenv ã®åºæ¬çãªäœ¿ãæ¹ãããå¿çšçãªãã¯ããã¯ããã¹ããã©ã¯ãã£ã¹ãŸã§ãç¶²çŸ çã«è§£èª¬ããŸããåå¿è ã®æ¹ããããã§ã«å©çšããŠããããã©ããã«æ·±ãç¥ãããæ¹ãŸã§ãå¹ åºã圹ç«ã€æ å ±ããå±ãããŸãã
ð ã€ã³ã¹ããŒã«æ¹æ³
python-dotenv ã®ã€ã³ã¹ããŒã«ã¯éåžžã«ç°¡åã§ããPython ã®ããã±ãŒãžç®¡çããŒã«ã§ãã `pip` ã䜿ã£ãŠã以äžã®ã³ãã³ããå®è¡ããã ãã§ãã
pip install python-dotenv
ãããžã§ã¯ãããšã«ã©ã€ãã©ãªã®ããŒãžã§ã³ã管çããããã«ãä»®æ³ç°å¢ (venv, conda ãªã©) ãå©çšããããšã匷ãæšå¥šããŸããä»®æ³ç°å¢å ã§ã€ã³ã¹ããŒã«ããããšã§ãä»ã®ãããžã§ã¯ããšã®äŸåé¢ä¿ã®è¡çªãé²ãããšãã§ããŸãã
# ä»®æ³ç°å¢ãäœæ (äŸ: venv)
python -m venv myenv
# ä»®æ³ç°å¢ãæå¹å (Windows)
myenv\Scripts\activate
# ä»®æ³ç°å¢ãæå¹å (macOS/Linux)
source myenv/bin/activate
# ä»®æ³ç°å¢å
㧠python-dotenv ãã€ã³ã¹ããŒã«
pip install python-dotenv
ããã§ãããªãã® Python ç°å¢ã§ python-dotenv ãå©çšããæºåãæŽããŸããïŒ
ð° åºæ¬çãªäœ¿ãæ¹
python-dotenv ã®æãåºæ¬çãªäœ¿ãæ¹ã¯ã.env
ãã¡ã€ã«ãäœæããload_dotenv()
é¢æ°ãåŒã³åºããŠãã¡ã€ã«ã®å
容ãç°å¢å€æ°ãšããŠèªã¿èŸŒãããšã§ãã
1. `.env` ãã¡ã€ã«ã®äœæ
ãŸããPython ã¹ã¯ãªãããšåããã£ã¬ã¯ããªããŸãã¯èŠªãã£ã¬ã¯ããªã« .env
ãšããååã®ãã¡ã€ã«ãäœæããŸãããã¡ã€ã«ã®äžèº«ã¯ã以äžã®ãããªããŒãšå€ã®ãã¢åœ¢åŒã§èšè¿°ããŸãã
.env
ãã¡ã€ã«ã®äŸ:
# ããŒã¿ããŒã¹èšå®
DATABASE_URL=postgresql://user:password@host:port/database
DATABASE_NAME=mydatabase
# API ããŒ
API_KEY=your_super_secret_api_key
SECRET_KEY=another_secret
# å€éšãµãŒãã¹èšå®
SERVICE_ENDPOINT=https://api.example.com/v1
# ã³ã¡ã³ãã¯è¡é ã« # ãä»ããŸã
# DEBUG=True # ãã®è¡ã¯èªã¿èŸŒãŸããŸãã
# ã¹ããŒã¹ãå«ãå€ã¯ã¯ã©ãŒããªãã§ãOK (ãã ãæ··ä¹±ãé¿ããããã¯ã©ãŒãæšå¥š)
APP_TITLE=My Awesome Application
# ã¯ã©ãŒãã§å²ãããšãå¯èœ
EMAIL_SUBJECT='Hello from App'
ADMIN_EMAIL="admin@example.com"
# 空ã®å€
EMPTY_VAR=
æžåŒã®ãã€ã³ã:
- ããŒãšå€ã¯
=
ã§åºåããŸãã - ããŒåã¯å€§æåã®ã¹ããŒã¯ã±ãŒã¹ (äŸ:
DATABASE_URL
) ãäžè¬çã§ãã - è¡é ã®
#
ã¯ã³ã¡ã³ããšããŠæ±ãããèªã¿é£ã°ãããŸãã - å€ã«ã¹ããŒã¹ãå«ãŸããŠããŠããéåžžã¯ãã®ãŸãŸèšè¿°ã§ããŸãã
- å€ãã·ã³ã°ã«ã¯ã©ãŒã (
'
) ãŸãã¯ããã«ã¯ã©ãŒã ("
) ã§å²ãããšãã§ããŸããç¹æ®æåãæ¹è¡ãå«ãå Žåã«äŸ¿å©ã§ãããå¿ é ã§ã¯ãããŸããã - 空ã®å€ãèšå®ã§ããŸã (äŸ:
EMPTY_VAR=
)ã
2. Python ã¹ã¯ãªããã§ç°å¢å€æ°ãèªã¿èŸŒã
次ã«ãPython ã¹ã¯ãªããå
㧠python-dotenv
ãã€ã³ããŒãããload_dotenv()
é¢æ°ãåŒã³åºããŸãããã®é¢æ°ã¯ãã«ã¬ã³ããã£ã¬ã¯ããªãŸãã¯èŠªãã£ã¬ã¯ããªãé¡ã£ãŠ .env
ãã¡ã€ã«ãæ¢ããèŠã€ãã£ããã¡ã€ã«ã®å
容ãç°å¢å€æ°ãšããŠããŒãããŸãã
ç°å¢å€æ°ãèªã¿èŸŒãã åŸã¯ãæšæºã©ã€ãã©ãªã® os
ã¢ãžã¥ãŒã«ã䜿ã£ãŠå€ãååŸã§ããŸãã
main.py
(.env
ãšåããã£ã¬ã¯ããªã«ããå Žå):
import os
from dotenv import load_dotenv
# .env ãã¡ã€ã«ããç°å¢å€æ°ãèªã¿èŸŒã
# ãã®æç¹ã§ .env ãã¡ã€ã«ã®å
容ãç°å¢å€æ°ã«èšå®ããã
load_dotenv()
# ç°å¢å€æ°ãååŸãã
db_url = os.getenv("DATABASE_URL")
api_key = os.getenv("API_KEY")
app_title = os.getenv("APP_TITLE")
empty_var = os.getenv("EMPTY_VAR")
# ååšããªãããŒãæå®ãããš None ãè¿ã
non_existent_var = os.getenv("NON_EXISTENT_VAR")
print(f"ããŒã¿ããŒã¹URL: {db_url}")
print(f"APIããŒ: {api_key}")
print(f"ã¢ããªã¿ã€ãã«: {app_title}")
print(f"空ã®å€æ°: '{empty_var}'") # 空æåå '' ãååŸããã
print(f"ååšããªãå€æ°: {non_existent_var}")
# os.environ ã䜿ã£ãŠã¢ã¯ã»ã¹ããããšãå¯èœ (ããŒãååšããªãå Žå㯠KeyError ãçºçãã)
try:
secret_key = os.environ["SECRET_KEY"]
print(f"ã·ãŒã¯ã¬ããããŒ: {secret_key}")
except KeyError:
print("SECRET_KEY ã¯èšå®ãããŠããŸããã")
try:
missing_key = os.environ["MISSING_KEY"]
except KeyError:
print("MISSING_KEY ã¯èšå®ãããŠããŸããã") # ãã¡ããåºåããã
å®è¡çµæã®äŸ:
ããŒã¿ããŒã¹URL: postgresql://user:password@host:port/database
APIããŒ: your_super_secret_api_key
ã¢ããªã¿ã€ãã«: My Awesome Application
空ã®å€æ°: ''
ååšããªãå€æ°: None
ã·ãŒã¯ã¬ããããŒ: another_secret
MISSING_KEY ã¯èšå®ãããŠããŸããã
ãã€ã³ã:
load_dotenv()
ã¯ãã¹ã¯ãªããã®ã§ããã ãæ©ã段éã§åŒã³åºãã®ãäžè¬çã§ããããã«ãããä»ã®ã¢ãžã¥ãŒã«ãã€ã³ããŒããããåã«ç°å¢å€æ°ãèšå®ãããŠããç¶æ ã«ãªããŸããos.getenv("ããŒå", "ããã©ã«ãå€")
ã®ããã«ã第äºåŒæ°ã§ããã©ã«ãå€ãæå®ã§ããŸããããŒãååšããªãå Žåã«None
ã§ã¯ãªãæå®ããããã©ã«ãå€ãè¿ããŸããos.environ["ããŒå"]
ã¯ãããŒãååšããªãå Žåã«KeyError
äŸå€ãéåºããŸããå¿ é ã®èšå®å€ãååšãããã©ããããã§ãã¯ããã®ã«äŸ¿å©ã§ãã
ããã§ãåºæ¬çãªèšå®å€ã®èªã¿èŸŒã¿ã¯å®ç§ã§ãïŒ ð
ð `.env` ãã¡ã€ã«ã®è©³çŽ°ãªæžåŒ
.env
ãã¡ã€ã«ã¯ã·ã³ãã«ãªåœ¢åŒã§ãããããã€ãç¥ã£ãŠãããšäŸ¿å©ãªã«ãŒã«ãæ©èœããããŸãã
ã³ã¡ã³ã
è¡é ã« #
ã眮ããšããã®è¡ã¯ã³ã¡ã³ããšããŠç¡èŠãããŸããèšå®ã®èª¬æãªã©ãèšè¿°ããã®ã«äŸ¿å©ã§ãã
# ããã¯ã³ã¡ã³ãè¡ã§ã
KEY=VALUE # è¡ã®éäžããã®ã³ã¡ã³ãã¯ãµããŒããããŠããŸãã (VALUE#... ãšããŠè§£éãããå¯èœæ§ãã)
ã¯ã©ãŒããŒã·ã§ã³ (åŒçšç¬Š)
å€ã¯ã·ã³ã°ã«ã¯ã©ãŒã ('
) ãŸãã¯ããã«ã¯ã©ãŒã ("
) ã§å²ãããšãã§ããŸããç¹ã«ãå€ã®å
é ãæ«å°Ÿã«ã¹ããŒã¹ãå«ãããå Žåãã#
ãå€ã®äžéšãšããŠæ±ãããå Žåã«åœ¹ç«ã¡ãŸãã
SINGLE_QUOTED='Value with leading/trailing spaces '
DOUBLE_QUOTED="Another value with spaces "
# ã¯ã©ãŒãã䜿ããªãå ŽåãååŸã®ã¹ããŒã¹ã¯éåžžããªã ãããŸã (ã©ã€ãã©ãªã®æåã«ããå Žåãã)
NO_QUOTES= Value without explicit quotes
HASH_VALUE="This value contains a # character"
ã¯ã©ãŒãã§å²ãŸããå éšã®ã¯ã©ãŒãæåã¯ãéåžžãšã¹ã±ãŒãããå¿ èŠã¯ãããŸããããæåã¯ã©ã€ãã©ãªã®ããŒãžã§ã³ãèšå®ã«ãã£ãŠç°ãªãå¯èœæ§ãããããã泚æãå¿ èŠã§ãã
å€æ°ã®å±é (Expansion)
.env
ãã¡ã€ã«å
ã§ãä»ã®å€æ°ãåç
§ããŠå€ãçµã¿ç«ãŠãããšãã§ããŸãã${VARIABLE_NAME}
ãŸã㯠$VARIABLE_NAME
ã®åœ¢åŒã§èšè¿°ããŸãã
BASE_DIR=/path/to/project
LOG_FILE=${BASE_DIR}/logs/app.log
# $å€æ°å ã®åœ¢åŒã䜿ãã
BACKUP_DIR=$BASE_DIR/backups
# ããã©ã«ãå€ãèšå®å¯èœ (æªå®çŸ©ã®å Žåã«äœ¿çš)
# ${VARIABLE:-default}
UPLOAD_DIR=${UPLOAD_PATH:-${BASE_DIR}/uploads}
泚æ: å€æ°å±éã¯ããã©ã«ãã§æå¹ã§ãããload_dotenv(override=False)
ã®ããã« `override=False` ãæå®ãããšãæ¢åã®ç°å¢å€æ°ãäžæžãããªããããå±éãããå€æ°ãæåŸ
éãã«ãªããªãå ŽåããããŸãã
ãã®æ©èœã䜿ããšãå ±éã®ãã¹ãªã©ãäžç®æã§å®çŸ©ããŠäœ¿ãåãããããèšå®ã®ã¡ã³ããã³ã¹æ§ãåäžããŸãã
è€æ°è¡ã®å€
å€ãè€æ°è¡ã«ããã£ãŠèšè¿°ãããå Žåã¯ãããã«ã¯ã©ãŒã ("
) ã§å²ã¿ãæ¹è¡ããã®ãŸãŸå«ããããšãã§ããŸãã
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCqGKukO1De7zhZj6+H0qtjTkVxwTCpvKe4eCZ0
... (äžç¥) ...
-----END RSA PRIVATE KEY-----"
MULTI_LINE_MESSAGE="ããã¯äžè¡ç®ã§ãã
ããã¯äºè¡ç®ã§ãã"
Python ã¹ã¯ãªããã§ãããã®å€ãååŸãããšãæ¹è¡æå (\n
) ãå«ãã æååãšããŠååŸãããŸãã
import os
from dotenv import load_dotenv
load_dotenv()
private_key = os.getenv("PRIVATE_KEY")
message = os.getenv("MULTI_LINE_MESSAGE")
print("--- Private Key ---")
print(private_key)
print("\n--- Message ---")
print(message)
ãšã¯ã¹ããŒã (Export)
è¡é ã« export
ããŒã¯ãŒããä»ããããšãã§ããŸããããã¯äž»ã«ã·ã§ã«ã¹ã¯ãªãããšã®äºææ§ã®ããã®ãã®ã§ãpython-dotenv
ã®æåã«ã¯é垞圱é¿ããŸããã
export EXPORTED_VAR=some_value
NOT_EXPORTED=another_value
ã©ã¡ãã®å€æ°ã load_dotenv()
ã«ãã£ãŠç°å¢å€æ°ãšããŠèªã¿èŸŒãŸããŸãã
âïž `load_dotenv()` é¢æ°ã®è©³çŽ°ãªãã·ã§ã³
load_dotenv()
é¢æ°ã¯ãããã€ãã®äŸ¿å©ãªåŒæ°ãåãä»ããŸããããã«ãããèªã¿èŸŒã¿ã®æåã现ããå¶åŸ¡ã§ããŸãã
åŒæ°å | å | ããã©ã«ãå€ | 説æ |
---|---|---|---|
dotenv_path | str or Path | None | èªã¿èŸŒã .env ãã¡ã€ã«ã®ãã¹ãæ瀺çã«æå®ããŸããæå®ããªãå Žåãfind_dotenv() ã䜿ã£ãŠã«ã¬ã³ããã£ã¬ã¯ããªãã芪ãã£ã¬ã¯ããªãžé¡ã£ãŠãã¡ã€ã«ãæ¢çŽ¢ãããŸãã |
verbose | bool | False | True ã«ãããšã.env ãã¡ã€ã«ãèŠã€ãããªãã£ãå Žåããèªã¿èŸŒã¿ã«é¢ãã詳现ãªãããã°æ
å ±ãæšæºãšã©ãŒåºåã«åºåãããŸããåé¡è§£æ±ºæã«åœ¹ç«ã¡ãŸããð§ |
override | bool | False | ããã©ã«ãã§ã¯ãã·ã¹ãã ã«æ¢ã«ååšããç°å¢å€æ°ã¯ .env ãã¡ã€ã«ã®å€ã§äžæžããããŸãããTrue ã«èšå®ãããšã.env ãã¡ã€ã«ã®å€ã§æ¢åã®ç°å¢å€æ°ã匷å¶çã«äžæžãããŸãã |
stream | IO[str] or None | None | ãã¡ã€ã«ãã¹ã®ä»£ããã«ããã¡ã€ã«ãªããžã§ã¯ãã®ãããªã¹ããªãŒã ãæå®ããŠãããããç°å¢å€æ°ãèªã¿èŸŒãããšãã§ããŸããäŸãã°ããªã¢ãŒãããååŸããèšå®æ å ±ãªã©ãçŽæ¥èªã¿èŸŒãŸããå Žåã«å©çšã§ããŸãã |
encoding | str or None | 'utf-8' | .env ãã¡ã€ã«ã®æåãšã³ã³ãŒãã£ã³ã°ãæå®ããŸããé垞㯠UTF-8 ã§åé¡ãããŸããããç°ãªããšã³ã³ãŒãã£ã³ã°ã®ãã¡ã€ã«ãæ±ãå Žåã«æå®ããŸãã |
interpolate | bool | True | True ã®å Žåã.env ãã¡ã€ã«å
ã®å€æ°å±é (äŸ: ${VAR} ) ãè¡ããŸããFalse ã«ãããšå±éãè¡ããŸããã |
䜿çšäŸ
ç¹å®ã®ãã¹ã® `.env` ãã¡ã€ã«ãèªã¿èŸŒã¿ãæ¢åã®å€æ°ãäžæžããã:
from dotenv import load_dotenv
import os
# äºåã«ç°å¢å€æ°ãèšå®ããŠãã (äŸ: OSã¬ãã«ã§èšå®ãããŠããå Žå)
os.environ['EXISTING_VAR'] = 'original_value'
# ç¹å®ã®ãã¹ã«ãã .env ãã¡ã€ã«ãæå®ããäžæžããèš±å¯ãã
dotenv_path = '/path/to/your/custom.env'
load_dotenv(dotenv_path=dotenv_path, override=True, verbose=True)
# custom.env ã« EXISTING_VAR=new_value ãããã°äžæžãããã
print(os.getenv('EXISTING_VAR'))
泚æ: `override=False` (ããã©ã«ã) ã®å Žåããã `os.environ[‘EXISTING_VAR’]` ãæ¢ã«ååšããŠãããã.env
ãã¡ã€ã«ã« `EXISTING_VAR` ãå®çŸ©ãããŠããŠãããã®å€ã¯ç¡èŠãããå
ã® `original_value` ãä¿æãããŸãã
ãã¡ã€ã«ãèŠã€ãããªãå Žåã«èŠåã衚瀺ãã:
from dotenv import load_dotenv
# ååšããªããã¹ãæå®ããŠã¿ã
load_dotenv(dotenv_path='/non/existent/.env', verbose=True)
# -> æšæºãšã©ãŒåºåã«ãã¡ã€ã«ãèŠã€ãããªãæšã®ã¡ãã»ãŒãžã衚瀺ããã
ãããã®ãªãã·ã§ã³ã䜿ãããªãããšã§ãããæè»ãªèšå®ç®¡çãå¯èœã«ãªããŸãã
ð ïž é«åºŠãªäœ¿ãæ¹ãšé¢é£é¢æ°
python-dotenv
㯠load_dotenv()
以å€ã«ãã䟿å©ãªé¢æ°ãæäŸããŠããŸãã
dotenv_values(): ç°å¢å€æ°ãèšå®ããã«èŸæžãšããŠèªã¿èŸŒã
load_dotenv()
㯠.env
ãã¡ã€ã«ã®å
容ãçŽæ¥ os.environ
ã«èšå®ããŸãããdotenv_values()
ã¯ç°å¢å€æ°ãå€æŽããããã¡ã€ã«ã®å
容ã Python ã®èŸæž (dict
) ãšããŠè¿ããŸãã
from dotenv import dotenv_values
import os
# .env ãã¡ã€ã«ã®å
容ãèŸæžãšããŠååŸ
config = dotenv_values(".env") # åŒæ°ã¯ load_dotenv ãšåæ§ã«æå®å¯èœ
db_url = config.get("DATABASE_URL")
api_key = config.get("API_KEY")
print(f"ããŒã¿ããŒã¹URL (from dict): {db_url}")
print(f"APIã㌠(from dict): {api_key}")
# os.environ ã«ã¯åœ±é¿ãäžããªã
print(f"ç°å¢å€æ°ã« DB_URL ãååšããã: {'DATABASE_URL' in os.environ}") # -> False (load_dotenv ãåŒãã§ããªãå Žå)
ãã®é¢æ°ã¯ãç°å¢å€æ°ãçŽæ¥æ±æããããªãå Žåããèšå®å€ãããã°ã©ã å ã§ãªããžã§ã¯ããšããŠæ±ãããå Žåã«äŸ¿å©ã§ãã
find_dotenv(): `.env` ãã¡ã€ã«ã®ãã¹ãæ¢çŽ¢ãã
load_dotenv()
ã dotenv_values()
ã¯å
éšã§ãã®é¢æ°ã䜿ãã.env
ãã¡ã€ã«ãæ¢ããŠããŸãããã®é¢æ°ãçŽæ¥äœ¿ãããšã§ãå®éã«ã©ã® .env
ãã¡ã€ã«ãèªã¿èŸŒãŸããã®ãã確èªã§ããŸãã
from dotenv import find_dotenv, load_dotenv
# .env ãã¡ã€ã«ã®ãã¹ãæ¢çŽ¢
# filename: æ¢ããã¡ã€ã«å (ããã©ã«ã㯠'.env')
# raise_error_if_not_found: èŠã€ãããªãå Žåã«ãšã©ãŒãéåºããã (ããã©ã«ã㯠False)
# usecwd: ã«ã¬ã³ããã£ã¬ã¯ããªãæ¢çŽ¢å¯Ÿè±¡ã«å«ããã (ããã©ã«ã㯠False)
try:
dotenv_file_path = find_dotenv(raise_error_if_not_found=True, usecwd=True)
print(f".env ãã¡ã€ã«ãèŠã€ãããŸãã: {dotenv_file_path}")
# èŠã€ãã£ããã¹ã䜿ã£ãŠèªã¿èŸŒã
load_dotenv(dotenv_path=dotenv_file_path)
except IOError:
print(".env ãã¡ã€ã«ãèŠã€ãããŸããã§ããã")
æ¢çŽ¢ã¯ãæå®ãããéå§ãã£ã¬ã¯ã㪠(ããã©ã«ãã¯ã«ã¬ã³ããã£ã¬ã¯ããªã®èŠª) ããå§ãŸãã芪ãã£ã¬ã¯ããªãžãšé¡ã£ãŠè¡ãããŸãã
set_key() ãš unset_key(): `.env` ãã¡ã€ã«ãããã°ã©ã ããç·šéãã
ãããã®é¢æ°ã䜿ããšãPython ã¹ã¯ãªãããã .env
ãã¡ã€ã«ã®å
容ãæžãæããããšãã§ããŸãã
from dotenv import set_key, unset_key, find_dotenv, get_key
dotenv_path = find_dotenv() # ãŸã .env ãã¡ã€ã«ã®ãã¹ãååŸ
# æ°ããããŒãšå€ãè¿œå ãŸãã¯æŽæ°
# set_key(dotenv_path, key_to_set, value_to_set, quote_mode='always', export=False, encoding='utf-8')
# quote_mode: 'always' (åžžã«ã¯ã©ãŒã), 'auto' (å¿
èŠãªãã¯ã©ãŒã), 'never' (ã¯ã©ãŒãããªã)
success, key, value = set_key(dotenv_path, "NEW_VARIABLE", "new_value")
if success:
print(f"ã㌠'{key}' ãå€ '{value}' ã§èšå®ããŸããã")
success, key, value = set_key(dotenv_path, "API_KEY", "updated_api_key_123", quote_mode="always")
if success:
print(f"ã㌠'{key}' ãå€ '{value}' ã§æŽæ°ããŸããã")
# .env ãã¡ã€ã«ããããŒãååŸãã get_key()
current_api_key = get_key(dotenv_path, "API_KEY")
print(f"çŸåšã® API_KEY: {current_api_key}") # -> updated_api_key_123
# ããŒãåé€ãã
# unset_key(dotenv_path, key_to_unset, quote_mode='always', encoding='utf-8')
success, key = unset_key(dotenv_path, "NEW_VARIABLE")
if success:
print(f"ã㌠'{key}' ãåé€ããŸããã")
# åé€ããããç¢ºèª (get_key ã¯èŠã€ãããªããš None ãè¿ã)
deleted_key_value = get_key(dotenv_path, "NEW_VARIABLE")
print(f"åé€åŸã® NEW_VARIABLE: {deleted_key_value}") # -> None
泚æ: ãããã®é¢æ°ã¯çŽæ¥ .env
ãã¡ã€ã«ãæžãæããŸããæäœã«ã¯åå泚æããå¿
èŠã§ããã°ããã¯ã¢ãããåãããã«ããŠãã ãããéåžžãã¢ããªã±ãŒã·ã§ã³ã®å®è¡æã«èšå®ãã¡ã€ã«ãåçã«æžãæããããšã¯çšã§ãäž»ã«èšå®ç®¡çããŒã«ããããã€ã¹ã¯ãªãããªã©ã§å©çšãããããšãèããããŸãã
ã¹ããªãŒã ããã®èªã¿èŸŒã¿
load_dotenv(stream=...)
ã dotenv_values(stream=...)
ã䜿ããšããã¡ã€ã«ä»¥å€ã®ãœãŒã¹ (æååããããã¯ãŒã¯çµç±ã§ååŸããããŒã¿ãªã©) ããèšå®ãèªã¿èŸŒããŸãã
import io
from dotenv import load_dotenv, dotenv_values
import os
# æååããã¡ã€ã«ã®ããã«æ±ã StringIO
dotenv_content = """
STREAM_VAR=Hello from stream!
ANOTHER_STREAM_VAR=12345
"""
stream = io.StringIO(dotenv_content)
# ã¹ããªãŒã ããèªã¿èŸŒãã§ç°å¢å€æ°ã«èšå®
load_dotenv(stream=stream)
print(os.getenv("STREAM_VAR")) # -> Hello from stream!
# ã¹ããªãŒã ãå床䜿ãããã«äœçœ®ãå
é ã«æ»ã
stream.seek(0)
# ã¹ããªãŒã ããèªã¿èŸŒãã§èŸæžãšããŠååŸ
config_from_stream = dotenv_values(stream=stream)
print(config_from_stream.get("ANOTHER_STREAM_VAR")) # -> 12345
ããã«ãããèšå®æ å ±ã®ååŸå ããã¡ã€ã«ã·ã¹ãã ã«éå®ãããªããªããããæè»ãªã·ã¹ãã æ§ç¯ãå¯èœã«ãªããŸãã
ð¡ ãŠãŒã¹ã±ãŒã¹ãšãã¹ããã©ã¯ãã£ã¹
python-dotenv ã¯æ§ã ãªå Žé¢ã§åœ¹ç«ã¡ãŸãããå¹æçã«äœ¿ãããã«ã¯ããã€ãã®ãã¹ããã©ã¯ãã£ã¹ããããŸãã
Web ãã¬ãŒã ã¯ãŒã¯ (Django, Flask) ãšã®é£æº
Django ã Flask ãªã©ã® Web ãã¬ãŒã ã¯ãŒã¯ã§ã¯ãèšå®ç®¡çã« python-dotenv ãå°å ¥ããã®ãäžè¬çã§ãã
Flask ã®äŸ (app.py
):
from flask import Flask
import os
from dotenv import load_dotenv
# ã¢ããªã±ãŒã·ã§ã³ã®åæååã« .env ãèªã¿èŸŒã
load_dotenv()
app = Flask(__name__)
# ç°å¢å€æ°ããèšå®ãèªã¿èŸŒã
app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'default-secret-key') # ããã©ã«ãå€ãæå®å¯èœ
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URL')
app.config['DEBUG'] = os.getenv('DEBUG', 'False').lower() in ('true', '1', 't') # æååãboolã«å€æ
@app.route('/')
def index():
return f"Hello! Debug mode is: {app.config['DEBUG']}"
if __name__ == '__main__':
# ç°å¢å€æ°ããããŒããååŸ (äŸ)
port = int(os.getenv('PORT', 5000))
app.run(host='0.0.0.0', port=port)
Django ã®äŸ (settings.py
):
import os
from pathlib import Path
from dotenv import load_dotenv
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# .env ãã¡ã€ã«ãèªã¿èŸŒã (BASE_DIR ã®èŠªãã£ã¬ã¯ããªãªã©ãæ¢ãå Žåããã)
# ãããžã§ã¯ãã«ãŒãã« .env ã眮ãããšãå€ã
dotenv_path = BASE_DIR.parent / '.env' # or BASE_DIR / '.env' depending on structure
load_dotenv(dotenv_path=dotenv_path)
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/stable/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.getenv('DJANGO_SECRET_KEY', 'fallback-unsafe-secret-key')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = os.getenv('DEBUG', 'False').lower() in ('true', '1', 't')
ALLOWED_HOSTS = os.getenv('DJANGO_ALLOWED_HOSTS', '127.0.0.1,localhost').split(',')
# Database
# https://docs.djangoproject.com/en/stable/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql', # äŸ
'NAME': os.getenv('DB_NAME'),
'USER': os.getenv('DB_USER'),
'PASSWORD': os.getenv('DB_PASSWORD'),
'HOST': os.getenv('DB_HOST'),
'PORT': os.getenv('DB_PORT'),
}
}
# ä»ã®èšå®ãåæ§ã« os.getenv() ã§èªã¿èŸŒã
# ...
ãã¬ãŒã ã¯ãŒã¯ã®èšå®ãã¡ã€ã«ã®ã§ããã ãæ©ã段é㧠`load_dotenv()` ãåŒã³åºãã®ããã€ã³ãã§ãã
Docker ç°å¢ã§ã®å©çš
Docker ã³ã³ããå
ã§ã¢ããªã±ãŒã·ã§ã³ãå®è¡ããå Žåã§ããpython-dotenv ã¯æå¹ã§ããéçºäžã¯ .env
ãã¡ã€ã«ãã³ã³ããã«ããŠã³ããŸãã¯ã³ããŒããŠå©çšããæ¬çªç°å¢ã§ã¯ Docker ã®ç°å¢å€æ°æ©èœ (docker run -e
ã docker-compose.yml
ã® environment
) ã䜿ã£ãŠèšå®ã泚å
¥ããã®ãäžè¬çã§ãã
Dockerfile (éçºçšäŸ):
FROM python:3.10-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
# .env ãã¡ã€ã«ãååšããããšãåæãšãã (docker-compose.yml ãªã©ã§ããŠã³ããã)
# CMD ["python", "main.py"] ãªã©ãã¢ããªã±ãŒã·ã§ã³ã®èµ·åã³ãã³ã
# éçºäžã¯ load_dotenv() ã .env ãèªã
# æ¬çªç°å¢åãã«ã¯ .env ãå«ãããç°å¢å€æ°ãå€éšãã泚å
¥ãã
# äŸ: docker run -e API_KEY='prod_key' ... myapp
load_dotenv()
ã¯ãoverride=False
(ããã©ã«ã) ã®å ŽåãDocker åŽã§èšå®ãããç°å¢å€æ°ãåªå
ãããããéçºç°å¢ (.env
ãã¡ã€ã«) ãšæ¬çªç°å¢ (Docker ã®ç°å¢å€æ°) ã§åãã³ãŒãããŒã¹ã䜿ãåãããããªããŸãã
ðš `.env` ãã¡ã€ã«ã `.gitignore` ã«è¿œå ããïŒ (æéèŠ)
.env
ãã¡ã€ã«ã«ã¯ãAPI ããŒããã¹ã¯ãŒããªã©ã®æ©å¯æ
å ±ãå«ãŸããããšãå€ãããã絶察㫠Git ãªã©ã®ããŒãžã§ã³ç®¡çã·ã¹ãã ã«ã³ãããããŠã¯ãããŸããã
ãããžã§ã¯ãã®ã«ãŒãã«ãã .gitignore
ãã¡ã€ã«ã«ã以äžã®è¡ãè¿œå ããŠãã ããã
# .gitignore
*.pyc
__pycache__/
myenv/ # ä»®æ³ç°å¢ãã©ã«ã
*.db
*.sqlite3
# --- éèŠ ---
# .env ãã¡ã€ã«ãé€å€ãã
.env
ãããå¿ãããšãæå³ããæ©å¯æ å ±ãå ¬éãªããžããªãªã©ã«ããã·ã¥ããŠããŸãå±éºæ§ããããŸããéåžžã«éèŠãªã®ã§ãå¿ ãèšå®ããŸãããã
`.env.example` ãã¡ã€ã«ã®æŽ»çš
.env
ãã¡ã€ã«èªäœã¯ã³ãããããŸããããã©ã®ãããªç°å¢å€æ°ãå¿
èŠãªã®ããä»ã®éçºè
ãå°æ¥ã®èªåã«ç€ºãããã«ã.env.example
(ãŸã㯠.env.template
ãªã©) ãšããååã®ãã¡ã€ã«ãäœæãããã¡ãã¯ã³ãããããã®ãè¯ããã©ã¯ãã£ã¹ã§ãã
.env.example
ã«ã¯ãå¿
èŠãªããŒåãšããããŒã®å€ã説æãèšè¿°ããŸãã
.env.example
ã®äŸ:
# ãã®ãã¡ã€ã«ã¯ .env ãã¡ã€ã«ã®ãã³ãã¬ãŒãã§ãã
# å®éã®å€ã¯ .env ãã¡ã€ã«ã«èšè¿°ãã.gitignore ã«è¿œå ããŠãã ããã
DATABASE_URL=postgresql://user:password@host:port/database
DATABASE_NAME=
API_KEY= # ããã«å®éã®APIããŒãå
¥å
SECRET_KEY= # ã¢ããªã±ãŒã·ã§ã³ã®ã·ãŒã¯ã¬ããããŒ
DEBUG=False # éçºæ㯠True ã«èšå®
SERVICE_ENDPOINT=https://api.example.com/v1
æ°ããéçºè
ããããžã§ã¯ãã«åå ããéããã® .env.example
ãã³ããŒã㊠.env
ãäœæããå¿
èŠãªå€ãåããã ãã§ç°å¢æ§ç¯ãå®äºããŸãã
æ¬çªç°å¢ã§ã®ç°å¢å€æ°ç®¡ç
éçºäžã¯ .env
ãã¡ã€ã«ã䟿å©ã§ãããæ¬çªç°å¢ã§ã¯ã»ãã¥ãªãã£ã管çã®èŠ³ç¹ãããç°ãªãæ¹æ³ã§ç°å¢å€æ°ãèšå®ããããšãæšå¥šãããŸãã
- OS ã®ç°å¢å€æ°: ãµãŒããŒèªäœã«ç°å¢å€æ°ãèšå®ããããããã€æé ã«çµã¿èŸŒãå¿ èŠããããŸãã
- ã³ã³ãããªãŒã±ã¹ãã¬ãŒã·ã§ã³ããŒã« (Kubernetes, Docker Swarm): Secret ã ConfigMap ãªã©ã®æ©èœã䜿ã£ãŠç°å¢å€æ°ãæ³šå ¥ããã
- PaaS (Heroku, AWS Elastic Beanstalk ãªã©): ãã©ãããã©ãŒã ãæäŸããç°å¢å€æ°èšå®æ©èœãå©çšããã
- èšå®ç®¡çããŒã« (AWS Systems Manager Parameter Store, HashiCorp Vault ãªã©): ããé«åºŠãªã·ãŒã¯ã¬ãã管çæ©èœãæäŸããããŒã«ãå©çšããã
python-dotenv 㯠override=False
ãããã©ã«ããªã®ã§ãæ¬çªç°å¢ã§ãããã®æ¹æ³ã§èšå®ãããç°å¢å€æ°ã¯ããã誀ã£ãŠ .env
ãã¡ã€ã«ããããã€ãããŠããŸã£ãŠãäžæžãããããæ¬çªçšã®èšå®ãåªå
ããããããå®å
šçãšããŠãæ©èœããŸãã
â ïž æ³šæç¹ãšãã©ãã«ã·ã¥ãŒãã£ã³ã°
python-dotenv ã䜿ãäžã§ãããã€ã泚æãã¹ãç¹ããåé¡ãçºçããå Žåã®å¯ŸåŠæ³ããããŸãã
ãã¡ã€ã«ãèŠã€ãããªã / èªã¿èŸŒãŸããªã
- å®è¡å Žæãš
.env
ã®äœçœ®é¢ä¿:load_dotenv()
ã¯ãããã©ã«ãã§ã¯ã¹ã¯ãªããã®å®è¡å Žæã§ã¯ãªããfind_dotenv()
ãèŠã€ãããã¹ (éåžžã¯ã«ã¬ã³ããã£ã¬ã¯ããªã芪ãã£ã¬ã¯ããª) ã®.env
ãèªã¿èŸŒã¿ãŸããã¹ã¯ãªããã®å®è¡å Žæãæ³å®ãšéãå Žåãèªã¿èŸŒãŸããªãããšããããŸãã- 察ç:
load_dotenv(dotenv_path='/path/to/.env')
ã§æ瀺çã«ãã¹ãæå®ããããload_dotenv(verbose=True)
ã§ã©ã®ãã¹ãæ¢ããŠããã確èªããŸãã
- 察ç:
- ãã¡ã€ã«åã®ã¿ã€ã: ãã¡ã€ã«åã
.env
ã«ãªã£ãŠããã確èªããŸã (äŸ:env
,.env.txt
ãªã©ã«ãªã£ãŠããªãã)ã load_dotenv()
ã®åŒã³åºãã¿ã€ãã³ã°: ç°å¢å€æ°ãåç §ããã³ãŒããããåã«load_dotenv()
ãåŒã³åºãããŠããã確èªããŸããç¹ã«ãã¢ãžã¥ãŒã«ã®ãããã¬ãã«ã§ç°å¢å€æ°ã䜿ã£ãŠããå Žåããã®ã¢ãžã¥ãŒã«ãã€ã³ããŒããããåã«load_dotenv()
ãå®è¡ããå¿ èŠããããŸããã¢ããªã±ãŒã·ã§ã³ã®ãšã³ããªãŒãã€ã³ã (app.py
ãmanage.py
ã®æåãªã©) ã§åŒã³åºãã®ãäžè¬çã§ãã
ç°å¢å€æ°ãæåŸ éãã«äžæžããããªã
override
ãªãã·ã§ã³: ããã©ã«ã (override=False
) ã§ã¯ãæ¢ã« OS ã¬ãã«ãªã©ã§èšå®ãããŠããç°å¢å€æ°ã¯.env
ãã¡ã€ã«ã®å€ã§äžæžããããŸãããæå³çã«äžæžããããå Žåã¯load_dotenv(override=True)
ã䜿çšããŸãã
ç¹æ®æåãã¯ã©ãŒãã®æ±ã
- å€ã«
#
ã=
ãå«ãã: å€ã«ãããã®æåãå«ãããå Žåã¯ãå€ãã¯ã©ãŒã ("..."
ãŸãã¯'...'
) ã§å²ãã®ãå®å šã§ãã - å€æ°ã®å±é (
$
): å€ã®äžã§$
æåããªãã©ã«ãšããŠäœ¿ãããå Žå (å€æ°å±éãæå³ããªãå Žå)ã\$
ã®ããã«ãšã¹ã±ãŒãããããå šäœãã·ã³ã°ã«ã¯ã©ãŒãã§å²ã ('...'
) ãªã©ã®æ¹æ³ããããŸã (æåã¯ããŒãžã§ã³ã«ããå¯èœæ§ãã)ããŸãã¯load_dotenv(interpolate=False)
ã§å€æ°å±éèªäœãç¡å¹ã«ããæ¹æ³ããããŸãã
ã©ã€ãã©ãªã®ããŒãžã§ã³
çšã«ãã©ã€ãã©ãªã®ããŒãžã§ã³éã§çŽ°ããæå (ã¯ã©ãŒãã®è§£éãå€æ°å±éã®æ¹æ³ãªã©) ãå€æŽãããå¯èœæ§ããããŸããããäºæãã¬åäœã«ééããå Žåã¯ã䜿çšããŠãã python-dotenv
ã®ããŒãžã§ã³ã確èªããå
¬åŒããã¥ã¡ã³ãããªãªãŒã¹ããŒããåç
§ããŠã¿ãŠãã ããã
pip show python-dotenv
åé¡ãçºçããå Žåã¯ãload_dotenv(verbose=True)
ãæå¹ã«ããŠãããã°æ
å ±ã確èªããã®ã第äžæ©ã§ããðµïžââïž
ð ãŸãšã
python-dotenv
ã¯ãPython ã¢ããªã±ãŒã·ã§ã³ã«ãããèšå®ç®¡çãåçã«æ¹åããŠãããã·ã³ãã«ãã€åŒ·åãªã©ã€ãã©ãªã§ãã
äž»ãªã¡ãªãã:
- â èšå®ãšã³ãŒãã®åé¢: æ©å¯æ å ±ãç°å¢äŸåã®èšå®ãã³ãŒãããåãé¢ããã
- ð ã»ãã¥ãªãã£åäž: API ããŒãªã©ã誀ã£ãŠããŒãžã§ã³ç®¡çã«ã³ããããããªã¹ã¯ãäœæž (
.gitignore
ãšã®äœµçšãåæ)ã - âïž ç°å¢éã®ç°¡åãªåãæ¿ã: éçºãã¹ããŒãžã³ã°ãæ¬çªç°å¢ããšã«
.env
ãã¡ã€ã«ãçšæ (ãŸãã¯ç°å¢å€æ°ã§äžæžã) ããã ãã§èšå®ãåãæ¿ããããã - ð€ ããŒã éçºã®å¹çå:
.env.example
ã䜿ã£ãŠå¿ èŠãªèšå®é ç®ãå ±æã§ããã - ð å°å ¥ã®å®¹æã: `pip install` ã㊠`load_dotenv()` ãåŒã³åºãã ãã§ããã«äœ¿ããã
.env
ãã¡ã€ã«ã®æžåŒãload_dotenv()
ã®ãªãã·ã§ã³ãé¢é£é¢æ° (dotenv_values
, find_dotenv
ãªã©) ãç解ãã.gitignore
ãžã®è¿œå ã .env.example
ã®æŽ»çšãšãã£ããã¹ããã©ã¯ãã£ã¹ãå®è·µããããšã§ãããå®å
šã§ã¡ã³ããã³ã¹æ§ã®é«ã Python ã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ã§ããŸãã
ãŸã å°å
¥ããŠããªãæ¹ã¯ããã²æ¬¡ã®ãããžã§ã¯ããã python-dotenv
ã掻çšããŠã¿ãŠãã ããïŒãã£ãšéçºäœéšãåäžããã¯ãã§ããHappy coding! ð
ã³ã¡ã³ã