概要(設定ファイル=「コードの外に出したルール表」)
設定ファイル(YAML)は、
「スクリプトの中にベタ書きしていた値(パス・日付・URL・モードなど)を、コードの外に出しておくための“ルール表”」
だと考えてください。
例えば、今こう書いているとします。
INPUT_DIR = "data/input"
OUTPUT_DIR = "data/output"
API_BASE_URL = "https://api.example.com/v1"
Pythonパスや URL を変えたくなるたびに、ソースコードを書き換えることになります。
これを config.yaml というファイルに出しておいて、Python 側は「その設定を読むだけ」にすると、
コードは変えずに設定だけ変えて挙動を変えられる
テスト用・本番用など環境ごとに設定ファイルを分けられる
他の人にも使いやすく説明しやすい
という状態になります。
ここでは、Python 自動化でよくあるパターンを題材にしながら、YAML の基礎から実戦的な使い方まで順番に解説します。
YAML の超基本(JSON より人間に優しい書き方)
YAML は「人間が読み書きしやすい辞書・リスト」
YAML は、ざっくり言うと「人間が読み書きしやすい JSON」みたいなものです。
中身自体は、Python 側で読み込むと、ほぼそのまま dict(辞書)や list(リスト)になります。
例えば、こんな config.yaml があったとします。
paths:
input_dir: "data/input"
output_dir: "data/output"
api:
base_url: "https://api.example.com/v1"
timeout: 5.0
retries: 3
mode: "production"
YAMLインデント(スペース)で階層を表現しています。paths.input_dir のような「階層付きの設定」を、見やすく整理できるのがポイントです。
JSON との違いイメージ
JSON で書くとこうなります。
{
"paths": {
"input_dir": "data/input",
"output_dir": "data/output"
},
"api": {
"base_url": "https://api.example.com/v1",
"timeout": 5.0,
"retries": 3
},
"mode": "production"
}
波かっこ・かっこ・カンマだらけで、人間が手で編集するには少ししんどいですよね。
YAML は、インデントと改行中心で書けるので、設定ファイル向きだとよく使われます。
Python から YAML 設定を読む基本(PyYAML)
ライブラリの準備と最小コード
Python で YAML を扱うには、一般的に PyYAML を使います。
pip install pyyaml
最小の読み込みコードはこんな感じです。
# config_loader.py
import yaml
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent
CONFIG_PATH = BASE_DIR / "config.yaml"
def load_config(path: Path = CONFIG_PATH) -> dict:
with path.open("r", encoding="utf-8") as f:
data = yaml.safe_load(f)
return data
if __name__ == "__main__":
config = load_config()
print(config)
print(config["paths"]["input_dir"])
Pythonyaml.safe_load で YAML を読み込むと、Python の dict / list に変換されます。
先ほどの config.yaml なら、
config["paths"]["input_dir"] # "data/input"
config["api"]["timeout"] # 5.0
config["mode"] # "production"
Pythonのように参照できます。
ここでの重要ポイントは、
コード側は「キーの名前」だけを知っていればよく、値そのものは YAML 側で自由に変えられる
パスや URL、タイムアウト秒数などをハードコードせずに済む
ということです。
自動化スクリプトと設定ファイルを分離する実例
例:データ収集 BOT の設定を YAML に出す
例えば「API からデータを取って CSV に保存する BOT」を考えます。
設定にしたいものは、だいたいこんな感じです。
どの API を叩くか(base_url、エンドポイント)
どのディレクトリに保存するか
タイムアウトやリトライ回数
動作モード(本番/検証)
これを config.yaml にまとめるとします。
paths:
base_dir: "data"
logs_dir: "logs"
api:
base_url: "https://api.example.com/v1"
timeout: 5.0
retries: 3
job:
mode: "production" # or "staging"
batch_size: 100
YAMLPython 側では、設定を読み込んでから処理に渡します。
# data_bot.py
import logging
from pathlib import Path
import requests
import yaml
BASE_DIR = Path(__file__).resolve().parent
CONFIG_PATH = BASE_DIR / "config.yaml"
def load_config(path: Path = CONFIG_PATH) -> dict:
with path.open("r", encoding="utf-8") as f:
return yaml.safe_load(f)
def setup_logging(logs_dir: Path):
logs_dir.mkdir(exist_ok=True)
log_file = logs_dir / "bot.log"
logging.basicConfig(
filename=log_file,
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(name)s - %(message)s"
)
def fetch_items(base_url: str, timeout: float):
url = f"{base_url}/items"
resp = requests.get(url, timeout=timeout)
resp.raise_for_status()
return resp.json()
def run_bot(config: dict):
paths_cfg = config["paths"]
api_cfg = config["api"]
job_cfg = config["job"]
data_dir = BASE_DIR / paths_cfg["base_dir"]
logs_dir = BASE_DIR / paths_cfg["logs_dir"]
data_dir.mkdir(exist_ok=True)
setup_logging(logs_dir)
logging.info(f"BOT開始 mode={job_cfg['mode']}")
items = fetch_items(api_cfg["base_url"], api_cfg["timeout"])
logging.info(f"取得件数: {len(items)}")
# ここに保存処理などを書く
def main():
config = load_config()
run_bot(config)
if __name__ == "__main__":
main()
Pythonここで深掘りしたいのは、「設定ファイルとロジックを分ける」感覚です。
コード側は、「config のどこに何が書いてあるか」(キー構造)だけ知っている
値そのもの(URL、パス、mode)は、完全に YAML 側に追い出した
この状態になると、
テスト環境用 config.staging.yaml
本番環境用 config.production.yaml
のようにファイルを分けて、起動時にどちらを読むか変えるだけで切り替えができます。
設定ファイル設計の重要ポイントを深掘りする
1. 「コードで変えないもの」を設定に、「頻繁に変えないもの」だけ出す
何でもかんでも設定ファイルに出せばいいわけではありません。
設定ファイルに出すべきものは、主にこういうものです。
環境ごとに変わる値(パス、URL、モード、batch_size など)
本番運用中にも変えたい可能性がある値(リトライ回数、タイムアウト、しきい値など)
逆に、ビジネスロジックそのもの(「こう計算する」「こう分岐する」など)を全部 YAML に埋め込もうとすると、
かえって分かりにくく、動作確認もしづらくなります。
目安としては、
「これはコードを書き換えずに変えたいか?」
と自分に問いかけて、Yes なら設定に出す、No ならコードに残す、くらいでちょうど良いです。
2. キー構造を丁寧に決める(paths / api / job などに分ける)
設定ファイルが大きくなってくると、
どこに何が書いてあるか分からない
同じ意味のパスが別名で複数書いてある
というカオス状態になりがちです。
それを防ぐために、トップレベルをざっくり「カテゴリ」で分けます。
例としては、
paths: ファイルパス・ディレクトリ関連
api: Web API 関連(base_url、timeout、retries 等)
job: バッチの動作モードや対象範囲
のようにするイメージです。
Python 側でも、
paths_cfg = config[“paths”]
api_cfg = config[“api”]
job_cfg = config[“job”]
とカテゴリごとに取り出せるので、見通しが良くなります。
3. デフォルト値と設定ファイルの優先順位
全部を YAML に書き切る必要はありません。
「ほぼ固定の値」は Python 側にデフォルトを持たせつつ、YAML で上書きできるようにする、という設計も有効です。
例えば、
DEFAULT_TIMEOUT = 5.0
timeout = config["api"].get("timeout", DEFAULT_TIMEOUT)
Pythonのようにしておけば、config.yaml に timeout がなければ 5.0 秒、
あればその値を使う、という柔らかい設計になります。
これを徹底すると、「設定ファイルがちょっと足りなくても動く」ので、
設定ファイル増殖時の移行(新旧フォーマットの混在)にも対応しやすくなります。
YAML の書き方でよく使うパターン(初心者向け)
キーと値、インデントの基本
最も基本は「キー: 値」です。
mode: "production"
batch_size: 100
timeout: 5.0
YAML文字列はダブルクオートなしでも書けますが、
日本語や特殊文字を含むときは "..." で囲んでおくと安心です。
インデントはスペース(通常2か4)で統一します。タブは使わない方が安全です。
paths:
input_dir: "data/input"
output_dir: "data/output"
YAMLpaths の下にある 2 行は、同じ階層のキーであることをスペースの位置で表現しています。
リスト(配列)を書きたいとき
例えば、「対象ユーザーIDのリスト」を設定にしたい場合。
targets:
users:
- 1001
- 1002
- 1003
YAMLPython 側で読み込むと、
config["targets"]["users"] # [1001, 1002, 1003]
Pythonという list になります。
処理対象の一覧や、「この API を使うかどうかのフラグの束」などに、リストはよく使います。
コメントで意味を残す
YAML では # 以降がコメントになります。
job:
mode: "production" # "staging" にするとテストモード
batch_size: 100 # 一度に処理する件数
YAMLコメントは「自分と他人への説明書」です。
設定の意味や、許容値の範囲などを書いておくと、壊しづらくなります。
設定ファイルと秘密情報(APIキーなど)の扱い
YAML に書いてはいけないもの(原則)
設定ファイルに何でも書きたくなりますが、
絶対に気をつけたいのが「秘密情報」です。
具体的には、
APIキー・トークン
パスワード
DB の接続文字列
などです。
これらを YAML に書いてしまうと、
Git に乗って漏れる
他の人に設定ファイルを渡したときに漏れる
など、かなり危険です。
秘密情報は環境変数、その他は YAML に
実務的には、
秘密情報(APIキーなど) → 環境変数(os.environ)
それ以外の設定(URL、パス、モードなど) → YAML
という分業がよく使われます。
例えば、YAML には「どのサービスを使うか」だけ書き、
api:
base_url: "https://api.example.com/v1"
timeout: 5.0
YAML実際のキーは環境変数から読みます。
import os
API_KEY = os.environ.get("MY_API_KEY")
Pythonこのようにすると、ソースや config.yaml を他人と共有しても、
秘密そのものは環境側にしか存在しない、という状態を保てます。
まとめ(設定ファイル+YAMLは「コードを長生きさせる」ための土台)
Python 自動化と YAML 設定ファイルを結びつけて整理すると、ポイントはこうなります。
設定ファイルは、「環境や運用に応じて変わる値」をコードから切り離すための“ルール表”。
YAML は JSON より人間が読み書きしやすく、階層化された設定(paths / api / job など)を綺麗に表現できる。
PyYAML(yaml.safe_load)で YAML を dict として読み込み、コード側は「キー構造だけ」を前提にロジックを書く。
何でもかんでも設定に出すのではなく、「コードを書き換えずに変えたいもの」だけを YAML に出す。
秘密情報は環境変数、その他の設定は YAML に分けて扱うことで、安全性と運用性を両立する。
このスタイルが身につくと、
今までは「パスを書き換えて保存して…」とやっていたスクリプトが、
config.yaml をちょっと変えるだけで、別環境・別条件でも動かせるようになります。
