Pythonでアプリケーションを作るとき、意外と迷うのが設定ファイルの形式です。
代表的なものには、次の3種類があります。
- JSON
- YAML
- TOML
以前、決まった時間にラジオ体操を自動再生するプログラムを作ったときは、設定ファイルにJSONを使いました。
JSONはPythonから扱いやすく、構造も分かりやすい形式です。しかし、実際に使ってみると一つ気になる点がありました。
JSONにはコメントを書けません。
たとえば、音声ファイルの保存場所を設定していたとしても、「これは何のパスなのか」「なぜこの値にしているのか」といった説明を設定ファイル内に残せません。
{
"audio_path": "/home/user/music/radio.mp3",
"start_time": "06:30"
}
設定項目が少ないうちは問題ありません。
しかし、しばらく時間がたってから設定ファイルを見直すと、何のための設定だったのか分からなくなることがあります。
そこで候補になるのが、YAMLとTOMLです。
TOMLは人間が読みやすい
TOMLは、基本的に次のような書き方をします。
# ラジオ体操の音声ファイル
audio_path = "/home/user/music/radio.mp3"
# 毎朝の再生時刻
start_time = "06:30"
# 自動再生を有効にする
enabled = true
基本的には、次の形式です。
設定名 = 値
文字列はダブルクォーテーションで囲みます。
audio_path = "/home/user/music/radio.mp3"
数値は、そのまま記述できます。
volume = 80
有効・無効のような真偽値は、trueまたはfalseで表します。
enabled = true
コメントは、行の先頭に#を付けて書きます。
# 自動再生を有効にする
enabled = true
設定値の後ろにコメントを書くこともできます。
volume = 80 # 音量
設定をグループごとに分けることもできます。
[audio]
path = "/home/user/music/radio.mp3"
volume = 80
[schedule]
start_time = "06:30"
enabled = true
この例では、音声関係の設定をaudio、実行時刻関係の設定をscheduleに分けています。
設定項目が増えても、比較的見通しを保ちやすい書き方です。
リストも記述できる
複数の曜日やファイルを設定したい場合は、リストも使えます。
days = ["monday", "tuesday", "wednesday"]
複数行に分けて書くこともできます。
days = [
"monday",
"tuesday",
"wednesday"
]
ラジオ体操を平日だけ実行したい場合は、次のような設定にできます。
[schedule]
start_time = "06:30"
enabled = true
days = [
"monday",
"tuesday",
"wednesday",
"thursday",
"friday"
]
PythonからTOMLを読み込む
Python 3.11以降では、標準ライブラリのtomllibを使ってTOMLファイルを読み込めます。
設定ファイルをconfig.tomlという名前で保存したとします。
[audio]
path = "/home/user/music/radio.mp3"
volume = 80
[schedule]
start_time = "06:30"
enabled = true
Python側では、次のように読み込みます。
import tomllib
with open("config.toml", "rb") as file:
config = tomllib.load(file)
audio_path = config["audio"]["path"]
volume = config["audio"]["volume"]
start_time = config["schedule"]["start_time"]
enabled = config["schedule"]["enabled"]
print(audio_path)
print(volume)
print(start_time)
print(enabled)
TOMLのグループは、Pythonでは辞書のように扱えます。
config["audio"]["path"]
この書き方で、次の設定値を取得しています。
[audio]
path = "/home/user/music/radio.mp3"
ただし、標準ライブラリのtomllibは読み込み専用です。
PythonからTOMLファイルを書き換えたい場合は、tomli-wやtomlkitなどの外部ライブラリが必要になります。
YAMLは複雑な設定に強い
YAMLは、階層の深い設定やリストをすっきり表現できます。
audio:
path: /home/user/music/radio.mp3
volume: 80
schedule:
start_time: "06:30"
enabled: true
days:
- monday
- tuesday
- wednesday
設定項目が増えて構造が複雑になった場合、YAMLはとても便利です。
一方で、YAMLはインデントに意味があります。
たとえば、次のようにスペースの位置がずれると、意図した構造にならない可能性があります。
schedule:
start_time: "06:30"
enabled: true
見た目では小さな違いですが、読み込みエラーになることがあります。
タブとスペースの違いや、インデントの深さにも注意しなければなりません。
小規模な個人用アプリでは、YAMLの柔軟さが、かえって扱いにくさにつながることもあります。
JSONが向いている場面
JSONでは、次のように設定を書きます。
{
"audio": {
"path": "/home/user/music/radio.mp3",
"volume": 80
},
"schedule": {
"start_time": "06:30",
"enabled": true
}
}
JSONはコメントを書けませんが、悪い形式というわけではありません。
次のような用途では、今でもJSONが使いやすいでしょう。
- プログラム同士でデータを受け渡す
- Web APIのレスポンスを保存する
- プログラムが自動生成・自動更新する
- 設定内容を人間があまり編集しない
JSONは仕様が比較的単純で、多くのプログラミング言語から扱えます。
「人間が直接編集する設定ファイル」というより、「プログラム同士が交換するデータ」に向いている形式だと思います。
同じ設定を3形式で比較する
同じ内容をJSON、YAML、TOMLで書くと、違いが分かりやすくなります。
JSON
{
"audio": {
"path": "/home/user/music/radio.mp3",
"volume": 80
},
"schedule": {
"start_time": "06:30",
"enabled": true
}
}
YAML
audio:
path: /home/user/music/radio.mp3
volume: 80
schedule:
start_time: "06:30"
enabled: true
TOML
[audio]
path = "/home/user/music/radio.mp3"
volume = 80
[schedule]
start_time = "06:30"
enabled = true
こうして比べてみると、TOMLは設定名 = 値という形がはっきりしていて、人間が読んだときに理解しやすいと感じます。
どれを選べばいいのか
私なりに整理すると、次のようになります。
| 形式 | 向いている用途 | 注意点 |
|---|---|---|
| JSON | データ交換、自動生成される設定 | コメントを書けない |
| YAML | 複雑で階層の深い設定 | インデントミスが起きやすい |
| TOML | 人間が手作業で編集する設定 | 非常に複雑な構造には不向き |
個人で作るPythonアプリケーションで、設定ファイルを自分が直接編集するなら、まずはTOMLを選ぶのがよさそうです。
特に、次のような設定にはTOMLが向いています。
- ファイルやフォルダーのパス
- 実行時刻
- URL
- 処理を有効・無効にする設定
- 数値のしきい値
- ログの出力レベル
- ブラウザーやドライバーの設定
- CSVファイルの保存先
たとえば、スクレイピングプログラムなら、次のような設定が考えられます。
[files]
input_csv = "/home/user/data/input.csv"
output_csv = "/home/user/data/output.csv"
log_file = "/home/user/logs/scraping.log"
[browser]
headless = true
timeout = 30
[scraping]
retry_count = 3
wait_seconds = 2
[price]
recommended_rate = 1.08
normal_rate = 1.10
プログラムの中に直接書いていた数値やパスをTOMLへ移動しておけば、Pythonコードを書き換えずに設定を変更できます。
TOMLは開発ツールでも使われている
TOMLはLinuxそのものの設定ファイルで大量に使われているというより、最近のプログラミング言語や開発ツールでよく採用されています。
代表的な例が、Pythonのpyproject.tomlです。
[project]
name = "radio-exercise"
version = "1.0.0"
description = "指定時刻にラジオ体操を再生するアプリ"
Pythonパッケージの依存関係を書くこともできます。
[project]
name = "radio-exercise"
version = "1.0.0"
dependencies = [
"pygame",
"schedule"
]
Rustでも、プロジェクト設定や依存ライブラリの管理にCargo.tomlを使います。
[package]
name = "sample-app"
version = "0.1.0"
edition = "2024"
[dependencies]
PythonやRustを触るなら、TOMLの書き方に慣れておいて損はありません。
パスを書くときの注意
Windowsのパスには、バックスラッシュが使われます。
C:\Users\takaaki\Music\radio.mp3
TOMLの通常の文字列では、バックスラッシュが特殊文字として扱われることがあります。
そのため、バックスラッシュを二つ書く方法があります。
audio_path = "C:\\Users\\takaaki\\Music\\radio.mp3"
または、シングルクォーテーションを使った文字列にすると、比較的そのまま書けます。
audio_path = 'C:\Users\takaaki\Music\radio.mp3'
Windowsでも、Python側で問題がなければ、スラッシュを使う方法もあります。
audio_path = "C:/Users/takaaki/Music/radio.mp3"
パスを設定ファイルに書く場合は、この違いを覚えておくとよさそうです。
パスワードは直接書かないほうがいい
TOMLには、文字列としてログイン情報を書くこともできます。
[login]
user_id = "sample-user"
password = "sample-password"
しかし、設定ファイルをGitHubなどへ誤って公開すると、パスワードも一緒に漏れてしまいます。
そのため、パスワードやAPIキーはTOMLへ直接書かず、環境変数や別の秘密情報用ファイルで管理するほうが安全です。
TOMLには、環境変数の名前だけを書いておく方法もあります。
[login]
user_id_env = "NETSEA_USER_ID"
password_env = "NETSEA_PASSWORD"
Python側で環境変数を読み込みます。
import os
user_id = os.environ["NETSEA_USER_ID"]
password = os.environ["NETSEA_PASSWORD"]
人間が読みやすい設定と、外部へ漏らしてはいけない秘密情報は、分けて管理することが大切です。
まとめ
設定ファイルには、それぞれ得意な用途があります。
JSONはプログラムで扱いやすいものの、コメントを書けません。
YAMLは複雑な構造を表現できますが、インデントに注意が必要です。
TOMLは書き方が比較的単純で、コメントも残せます。
# 出力するCSVファイル
output_csv = "/home/user/data/output.csv"
# 処理を有効にする
enabled = true
# タイムアウト秒数
timeout = 30
このように、設定の意味をコメントとして残せるため、人間が読んだり編集したりする設定ファイルとして、とても使いやすい形式です。
今後、Pythonで小さなアプリケーションを作るなら、まずはTOMLを設定ファイルの第一候補にしてみようと思います。
もちろん、すでにJSONで問題なく動いているプログラムを、無理にTOMLへ変更する必要はありません。
新しく作るプログラムから少しずつ試して、自分に合った形式を選ぶのが一番よさそうです。