M12 設定檔的世界
- 認出常見工具的設定檔用哪種格式、放在哪裏;
- 讀懂 VS Code 的 settings.json、GitHub Actions 的 workflow、docker-compose 和 Markdown 的 frontmatter;
- 認出這些設定檔裏 M8–M10 講過的陷阱,例如
python-version: 3.10變成3.1; - 改設定檔前後用程式檢查,一次只改一處。
1設定檔無處不在 Configuration everywhere
打開這個課程網站自己的倉庫,設定檔比課程內容還多:
| 工具 | 設定檔 | 格式 | 寫給誰讀 |
|---|---|---|---|
| VS Code | .vscode/settings.json、tasks.json |
JSON(准許註解) | 編輯器 |
| GitHub Actions | .github/workflows/*.yml |
YAML | GitHub 的伺服器 |
| Docker | compose.yaml |
YAML | Docker |
| Python 專案 | pyproject.toml(M1) |
TOML | uv、pip |
| Markdown 文件 | 檔案開頭 --- 之間 |
YAML | 網站產生器、Obsidian |
| Claude Code | .claude/settings.json |
JSON | Claude Code |
格式你都學過了。分別在於:每個工具只認自己那一套鍵名,而且各自有些自己的規矩。
2VS Code:准許註解的 JSON VS Code: JSON with comments
這個課程倉庫的 .vscode/settings.json(節錄):
{
// Markdown:Tab 鍵展開本課的 snippets
"[markdown]": {
"editor.tabCompletion": "onlySnippets",
"editor.wordWrap": "on"
},
"liveServer.settings.port": 5501
}
M8 說過 JSON 不准寫註解,用 json.loads 讀它果然報錯:
JSONDecodeError: Expecting property name enclosed in double quotes: line 2 column 3 (char 4)
因為 VS Code 的設定檔不是嚴格的 JSON,而是 JSONC(JSON with Comments):准許 // 和 /* */ 註解。給人改的設定檔需要註解,所以 VS Code 放寬了規則。
VS Code 編輯這些檔案時,會用 JSON Schema(M10)檢查:鍵名打錯,下面會出現波浪線;輸入時會自動列出可用的設定。這就是 M10 那套方法在日常工具裏的樣子。
3GitHub Actions:YAML 的陷阱 GitHub Actions
GitHub Actions 讓 GitHub 在你 push 之後自動執行檢查。設定寫在 .github/workflows/ 裏的 YAML 檔:
name: 檢查課程網站
on:
push:
branches: [main]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4 # 取出倉庫的內容
- uses: actions/setup-python@v5 # 安裝 Python
with:
python-version: "3.12"
- run: python tools/build.py --check
flowchart LR
E["on:push 到 main"] --> J["job:check<br/>runs-on: ubuntu-latest"]
J --> S1["step 1<br/>取出倉庫"]
S1 --> S2["step 2<br/>安裝 Python 3.12"]
S2 --> S3["step 3<br/>build.py --check"]
classDef e fill:#f1f1ef,stroke:#d3d1cb,color:#37352f
classDef s fill:#ffffff,stroke:#d3d1cb,color:#37352f
class E,J e
class S1,S2,S3 s
這類檔案常見兩個 M9 的陷阱:
python-version: 3.10會變成3.1(M9 的1.10)。GitHub 會去找 Python 3.1,結果失敗或者裝錯版本。這是 GitHub Actions 最常見的錯誤之一,所以上面寫成"3.12",版本號一律加引號;on:這個鍵,用 PyYAML 讀入會變成True(M9 的on)。GitHub 自己的讀法沒有問題,但你用 Python 讀 workflow 檔時,要寫wf[True],不是wf["on"]。
4docker-compose:端口要加引號 docker-compose: quote your ports
Docker 用 compose.yaml 描述要執行哪些服務:
services:
web:
image: nginx:1.27
ports:
- "8080:80" # 本機 8080 → 容器 80
- "2222:22" # 本機 2222 → 容器 22(SSH)
ports 的寫法是「本機端口:容器端口」。不加引號會怎樣?用 PyYAML 實測:
| 寫的 | 讀到 |
|---|---|
- 8080:80 |
'8080:80'(字串,沒事) |
- 2222:22 |
133342(六十進制:2222×60+22) |
冒號後面的數字小於 60,就會被當成六十進制(M9 的 9:30)。這是 PyYAML 和其他跟舊版 YAML 1.1 的工具的讀法;YAML 1.2 已經沒有六十進制(見 M9 的「YAML 1.1 與 1.2」)。但你無法保證每個讀這份檔的程式都跟 1.2,所以端口一律加引號,不用逐個判斷。
5Markdown 的 frontmatter Markdown frontmatter
這個課程的每一個單元,都是一個 Markdown 檔,開頭有一段用 --- 包住的 YAML,叫做 frontmatter:
---
title: 設定檔的世界
time: 約 45 分鐘
goals:
- 認出常見工具的設定檔用哪種格式、放在哪裏;
---
## 設定檔無處不在 …
網站產生器(包括本課的 tools/build.py)和 Obsidian 都這樣用:frontmatter 放這份文件的資料(標題、日期、標籤),下面才是內容。讀它的方法很簡單:用 --- 切開,中間那段交給 yaml.safe_load。本課的建置腳本就是這樣做的。
6Claude Code 的設定 Claude Code settings
Claude Code 的設定是 JSON,分三層,越下面越優先:
| 檔案 | 範圍 | 放進 Git 嗎 |
|---|---|---|
~/.claude/settings.json |
你自己,所有專案 | 不(在你的家目錄) |
.claude/settings.json |
這個專案,全組人共用 | 放 |
.claude/settings.local.json |
這個專案,只限你自己 | 不放 |
公司或學校的管理員還可以在這三層之上加一層受管理的設定(managed settings),它優先於這三層,個人和專案的設定都蓋不過它。
最常改的是權限,例如准許它執行哪些命令、禁止它讀哪些檔案:
{
"permissions": {
"allow": ["Bash(python3 tools/build.py:*)"],
"deny": ["Read(./.env)"]
}
}
這三層的分法,在很多工具裏都見到:個人設定、專案設定、只在自己電腦上的設定。密碼、API key 這類秘密,永遠不要寫進會放進 Git 的設定檔;要用的話,放在不入 Git 的檔案或環境變數裏。
7安全地修改設定檔 Editing config files safely
設定檔寫錯了,工具可能啟動不了,也可能靜靜地用錯的設定執行(M9 的挪威)。改之前、改之後,花一分鐘檢查:
flowchart LR
A["先 commit"] --> B["只改一處"]
B --> C["用程式讀"]
C -->|"報錯"| B
C -->|"讀得到"| D["印出型別"]
D --> E["讓工具使用"]
classDef s fill:#ffffff,stroke:#d3d1cb,color:#37352f
class A,B,C,D,E s
- 先 commit(git-course 的習慣):改壞了,一句命令就能退回;
- 一次只改一處:出問題時,你知道是哪一處;
- 用程式讀一次:
json.loads、yaml.safe_load、tomllib.loads,語法錯誤立即現形; - 印出改了的值和型別:抓 M9 那種「合法但猜錯」的錯誤;有 schema 的話,跑一次驗證(M10);
- 最後才讓工具使用新的設定。
連這一頁也不例外:本頁開頭的 frontmatter,學習目標裏有一句提到 python-version: 3.10。那個「冒號+空格」令 YAML 把整句讀成一個 dict,建置當場失敗。修法正是 M9 的規則:整句加引號。之後建置腳本加了一道檢查,學習目標不是文字就清楚地報出是哪一句。
8容易混淆 Easily confused
| 這兩樣 | 分別 |
|---|---|
| JSON 和 JSONC | 後者准許註解,是 VS Code 等工具用的;json.loads 讀不了。 |
GitHub 讀 on: 和 PyYAML 讀 on: |
GitHub 當它是鍵名 on;PyYAML 當它是 True。 |
python-version: 3.10 和 "3.10" |
前者讀成 3.1;後者才是 3.10。 |
8080:80 和 2222:22 |
前者 PyYAML 讀到字串;後者被跟 YAML 1.1 的工具(例如 PyYAML)讀成 133342。兩者都應加引號。 |
settings.json 和 settings.local.json |
前者全組共用、放進 Git;後者只限自己、不放。 |
| frontmatter 和內文 | 前者是 --- 之間的 YAML 資料;後者是文件內容。 |
9動手:設定檔巡禮 Hands-on: a tour of config files
- 下載
m12-config-tour.ipynb和m12-configs.zip,放進python-course資料夾; - 執行
uv run jupyter lab,打開 notebook,逐格執行。
zip 裏有小書店網站的五個設定檔:VS Code 設定、GitHub Actions workflow、docker-compose、一篇有 frontmatter 的網誌文章、Claude Code 設定。每個檔都藏了一個這單元講過的問題。你要逐個讀入、找出問題、修好,並寫一個函式,一次檢查全部設定檔。
m12-pipeline-eng.ipynb 和 pipeline.yaml:一份資料處理流程的設定檔,列出每個階段的腳本、輸入和輸出。用 JSON Schema 檢查格式,再用程式檢查「每個階段需要的輸入,前面的階段都有產生」。
M13 綜合專案:從香港天文台的開放資料取得真實的天氣 JSON,整理、統計、畫圖,寫成一份 notebook 報告,把整門課用過的工具串起來。