Day 28:設定管理で「安全に動くコード」を意識する
Day 28では、設定管理 をテーマに、
.env- 環境変数
- 秘密情報をコードに書かない
- 設定ファイル
といったキーワードを軸に、「安全で変更しやすいコード」を書く感覚を身につけていきます。 セキュリティの観点からもとても重要な内容ですので、ゆっくり丁寧に見ていきます。
なぜ設定管理が必要なのか
コードに「べた書き」すると何が困るか
まず、よくある「よくない例」から見てみます。
# よくない例:秘密情報をコードに直接書いている
DB_USER = "admin"
DB_PASSWORD = "super-secret-password" # ← これは危険です
DB_HOST = "localhost"
DB_NAME = "myapp"
Pythonこのようにコードの中に、
- データベースのパスワード
- APIキー
- トークン
などを直接書いてしまうと、次のような問題が起きます。
- セキュリティ上のリスク
- GitHubなどにコードを公開したとき、秘密情報も一緒に公開されてしまう
- 環境ごとの違いに対応しづらい
- 開発環境・テスト環境・本番環境で設定が違うのに、毎回コードを書き換える必要がある
- 変更に弱い
- パスワードや接続先が変わるたびにコードを修正しなければならない
そこで登場するのが、環境変数 や 設定ファイル、そして .env という仕組みです。
環境変数とは何か
OSが持っている「設定の入れ物」
環境変数(environment variables) は、
- OS(Windows / macOS / Linux)が持っている「設定の入れ物」
- プログラムから参照できる「キーと値」のペア
のようなものです。
例えば、PATH という環境変数には、
- 実行ファイルを探すためのディレクトリ一覧
が入っています。
Pythonから環境変数を読むには、os モジュールを使います。
import os
# 環境変数を取得します。存在しない場合は None が返ります。
path = os.getenv("PATH")
print("PATH:", path)
Pythonここでのポイントは、
os.getenv("変数名")で環境変数を取得できること- 環境変数は「コードの外側」にある設定であり、コードを変えずに値を変えられること
です。
秘密情報を環境変数から読む
パスワードやAPIキーをコードに書かない
データベースのパスワードなどの秘密情報は、 環境変数に入れておき、コードからはそれを読むようにするのが基本です。
import os
# 環境変数から秘密情報を読み取ります。
DB_USER = os.getenv("DB_USER")
DB_PASSWORD = os.getenv("DB_PASSWORD")
DB_HOST = os.getenv("DB_HOST", "localhost") # デフォルト値を指定することもできます。
DB_NAME = os.getenv("DB_NAME", "myapp")
print("DB_USER:", DB_USER)
print("DB_HOST:", DB_HOST)
Pythonここでの重要ポイントは、
- コードの中には「具体的なパスワード」を書いていないこと
- 実際の値は、OS側の環境変数に設定しておくこと
- 環境ごとに違う値を、コードを変えずに切り替えられること
です。
.envファイルとは何か
環境変数を「ファイルで管理」する
開発環境では、毎回OSの環境変数を設定するのは少し面倒です。 そこでよく使われるのが .env ファイル です。
.env ファイルは、次のような形式のテキストファイルです。
# .env ファイルの例
DB_USER=admin
DB_PASSWORD=super-secret-password
DB_HOST=localhost
DB_NAME=myapp
このファイルをプロジェクトのルートに置いておき、 Pythonから読み込んで環境変数として扱う、という使い方をします。
python-dotenvで .env を読み込む
.env を読み込むには、よく python-dotenv というライブラリが使われます。 (Day 22で学んだ pip でインストールできます。)
bash
pip install python-dotenv
Python側のコードは次のようになります。
from dotenv import load_dotenv
import os
# .env ファイルを読み込み、環境変数として設定します。
load_dotenv()
DB_USER = os.getenv("DB_USER")
DB_PASSWORD = os.getenv("DB_PASSWORD")
DB_HOST = os.getenv("DB_HOST", "localhost")
DB_NAME = os.getenv("DB_NAME", "myapp")
print("DB_USER:", DB_USER)
print("DB_HOST:", DB_HOST)
Pythonここでのポイントは、
.envに秘密情報を書き、コードからはos.getenvで読むこと.envは「環境ごとに切り替えられる設定ファイル」として扱えること.env自体は Gitにコミットしない(.gitignoreに入れる) のが基本であること
です。
設定ファイルで「環境ごとの違い」を整理する
設定ファイルの役割
環境変数は「秘密情報」や「環境ごとの違い」を扱うのに向いていますが、 それ以外の設定(ログレベル・タイムアウト・機能のON/OFFなど)は、 設定ファイル にまとめておくと管理しやすくなります。
設定ファイルの形式としては、
- JSON (
config.json) - YAML (
config.yaml) - INI (
config.ini) - Pythonファイル (
config.py)
など、さまざまな選択肢があります。
ここでは、初心者でも扱いやすい JSON を例にします。
JSON形式の設定ファイル例
config.json:
{
"app_name": "MyApp",
"log_level": "INFO",
"retry_count": 3,
"api_base_url": "https://api.example.com"
}
JSONPythonから読み込むコード:
import json
def load_config(path: str = "config.json") -> dict:
"""JSON形式の設定ファイルを読み込む関数です。"""
with open(path, "r", encoding="utf-8") as f:
config = json.load(f)
return config
def main():
config = load_config()
print("アプリ名:", config["app_name"])
print("ログレベル:", config["log_level"])
print("リトライ回数:", config["retry_count"])
print("APIベースURL:", config["api_base_url"])
if __name__ == "__main__":
main()
Pythonここでのポイントは、
- 設定値をコードから切り離し、
config.jsonにまとめていること - 設定を変えたいときは、コードではなく設定ファイルを編集すればよいこと
- 「設定」と「ロジック」を分けることで、コードが読みやすくなること
です。
「秘密情報」と「通常設定」を分けて考える
役割の分離がセキュリティの基本
ここまでの内容を整理すると、次のような分け方が見えてきます。
- 秘密情報(パスワード・APIキー・トークンなど)
- 環境変数や
.envに置く - Gitなどで共有しない
- 環境変数や
- 通常設定(ログレベル・タイムアウト・URLなど)
- 設定ファイル(JSON / YAML / INIなど)に置く
- チームで共有しても問題ないもの
この分け方を意識することで、
- セキュリティリスクを減らしつつ
- 設定変更に強いコード
を書けるようになります。
Day 28ミニテンプレート:設定管理入門スクリプト
最後に、Day 28で学んだ内容をまとめて試せる「設定管理入門スクリプト」のテンプレートを示します。
1. .env の例
.env:
DB_USER=admin
DB_PASSWORD=super-secret-password
DB_HOST=localhost
DB_NAME=myapp
2. config.json の例
{
"app_name": "MyApp",
"log_level": "INFO",
"retry_count": 3,
"api_base_url": "https://api.example.com"
}
JSON3. Pythonコード
# day28_config.py
# 設定管理入門の練習用スクリプト
from dotenv import load_dotenv
import os
import json
import logging
def load_env():
"""環境変数(.env)を読み込む関数です。"""
load_dotenv() # .env を読み込んで環境変数として設定します。
db_user = os.getenv("DB_USER")
db_password = os.getenv("DB_PASSWORD")
db_host = os.getenv("DB_HOST", "localhost")
db_name = os.getenv("DB_NAME", "myapp")
return {
"DB_USER": db_user,
"DB_PASSWORD": db_password,
"DB_HOST": db_host,
"DB_NAME": db_name,
}
def load_config(path: str = "config.json") -> dict:
"""JSON形式の設定ファイルを読み込む関数です。"""
with open(path, "r", encoding="utf-8") as f:
config = json.load(f)
return config
def setup_logging(log_level: str):
"""ログ設定を行う関数です。"""
level = getattr(logging, log_level.upper(), logging.INFO)
logging.basicConfig(
level=level,
format="%(asctime)s [%(levelname)s] %(message)s"
)
def main():
# .env から秘密情報を読み込みます。
env = load_env()
# 設定ファイルから通常設定を読み込みます。
config = load_config()
# ログ設定を行います。
setup_logging(config["log_level"])
logging.info("アプリケーションを開始します")
logging.info("アプリ名: %s", config["app_name"])
logging.info("APIベースURL: %s", config["api_base_url"])
logging.info("リトライ回数: %s", config["retry_count"])
logging.info("DB接続情報(ユーザー名のみ表示): %s@%s/%s",
env["DB_USER"], env["DB_HOST"], env["DB_NAME"])
# 実際のDB接続処理はここに書くイメージです。
# env["DB_PASSWORD"] はログに出さないようにします(重要)。
logging.info("アプリケーションを終了します")
if __name__ == "__main__":
main()
Pythonこのテンプレートでは、
.envから秘密情報を読み込みconfig.jsonから通常設定を読み込み- ログ設定を行いながらアプリケーションを動かす
という一連の流れを体験できます。
Day 28のまとめ
Day 28では、設定管理入門として、
- コードに秘密情報を「べた書き」する危険性
- 環境変数を使って、コードの外側に設定を置く考え方
.envファイルで開発環境の設定を簡単に管理する方法- 設定ファイル(JSONなど)で「通常設定」を整理する方法
- 「秘密情報」と「通常設定」を分けて扱うセキュリティの基本
をステップバイステップで学んでいただきました。
ここまで来ると、「ただ動くコード」から一歩進んで、 「安全で変更に強いコード」を意識して書く感覚が少し育っているはずです。 この感覚は、今後の実践Python編で、外部サービスや本番環境を扱うときに、 セキュリティと運用性を両立させるための大きな土台になっていきます。
