1. 如何在 Python 中讀取 YAML?|本文概要與目標讀者
想在 Python 中處理 YAML 的您
在 Python 中開發應用程式或工具時,會越來越多情況想要使用 YAML 格式來處理「設定檔」或「外部資料的管理」。特別是 YAML 比 JSON 更具可讀性,且能以簡單的描述方式撰寫,因此在工程師或資料科學家之間,也是一種極受歡迎的資料格式。 例如,以下這些用途就需要讀取 YAML:- 將 Web 應用程式或腳本的設定檔外部化
- 想在 Python 中解析Docker Compose 或 Kubernetes的設定檔
- 想用 YAML 管理機器學習框架的參數
另一方面,也經常聽到初學者說「不知道該如何讀取 YAML 檔案」「出現錯誤,無法順利讀取」等困擾。本文可學到的事
這篇文章將以易懂的方式,向初學者說明在 Python 中安全且確實讀取 YAML 檔案的方法。具體來說,將涵蓋以下重點:- YAML 檔案的基本結構與特點
- Python 中的讀取方法(
safe_load()
的用法) - 常見錯誤及其對策
- 多重文件讀取或設定檔的實務範例
此外,還會觸及安全性方面的注意事項,以及 load()
與 safe_load()
的差異等,不太為人知的情資。最後,還準備了常見問題(FAQ),您的疑問一定能迎刃而解。目標讀者
這篇文章的對象為以下人士:- 想在 Python 中使用 YAML 的初學者~中級者
- 需要處理設定檔的開發者
- 對 PyYAML 的用法感到不安的人
- 想詳細了解
safe_load()
或錯誤對應的人
如果您希望未來在 Python 開發中提升效率,則掌握 YAML 的處理方式將是重大的一步。 接下來的章節,將逐步說明 YAML 的概要及在 Python 中的處理方式。首先,從「YAML 是什麼?」開始吧。
2. YAML 是什麼?|與 JSON 的差異與特點簡單比較
YAML 是什麼?
YAML(讀作 yamu-er,或 yamuru)是「YAML Ain’t Markup Language(YAML 不是標記語言)」的遞迴縮寫,主要為了讓人類更容易讀寫結構化資料而設計的格式。與 Python 或 Ruby 等程式語言相性良好,常被用於設定檔或資料交換的場合。 YAML 使用縮排來表現階層結構,簡單且直觀的描述是其主要特點。與 JSON 的差異
YAML 與 JSON 用於類似的用途,但兩者有幾個明確的差異。以下比較代表性的項目。比較項目 | YAML | JSON |
---|
可讀性 | 高(對人類友好) | 中等(對機器友好) |
註解的記述 | 可能(使用 # ) | 不可 |
檔案大小 | 傾向較小(符號較少) | 稍大 |
資料結構的表現 | 自由度更高(複雜結構也 OK) | 以陣列・物件為中心 |
擴展性 | 高(可定義自有結構) | 有限制 |
支援情況 | 部分有限制 | 廣泛支援 |
YAML 的優點
使用 YAML 有以下優點:- 直觀的寫法:類似 Python 的縮排,容易掌握結構
- 可寫註解:方便在設定檔中添加補充說明
- 不冗長:不需要 JSON 般的中括弧或雙引號
- 對人類友好:非工程師也能輕鬆閱讀與修改
YAML 的使用場合
YAML 常被以下工具或系統使用:- Docker Compose(
docker-compose.yml
) - Kubernetes 的設定檔(Pod 或 Service 的定義)
- CI/CD 工具(GitHub Actions、GitLab CI 等)
- 機器學習函式庫(PyTorch Lightning 或 Hydra 等)
- Web 應用程式或腳本的設定檔
也就是說,學會處理 YAML 將在現代開發現場中成為強大的武器。3. 使用 Python 處理 YAML 的準備|PyYAML 的安裝
什麼是 PyYAML?
使用 Python 讀取或寫入 YAML 檔案時,通常會使用外部程式庫「PyYAML」。PyYAML 是一個基於 YAML 1.1 規格的簡單且功能豐富的程式庫,因為它不包含在 Python 的標準程式庫中,因此需要另外安裝。 使用 PyYAML 後,可以將 YAML 檔案作為 Python 的字典(dict
)或清單(list
)來處理。這樣一來,設定檔案的讀寫以及結構化資料的操作就能更直觀地進行。PyYAML 的安裝方法
PyYAML 的安裝非常簡單。如下所示,可以使用 pip
在命令列(或終端機)中安裝。pip install pyyaml
※如果環境中沒有 pip
,則使用 python -m pip install pyyaml
也沒問題。建議使用虛擬環境
如果想分離開發環境,建議在 虛擬環境(venv 或 conda) 中安裝。處理多個專案時,程式庫的版本管理會更容易。# 虛擬環境的建立
python -m venv venv
# 啟用虛擬環境
# Windows 的情況
venv\Scripts\activate
# macOS/Linux 的情況
source venv/bin/activate
# 安裝 PyYAML
pip install pyyaml
安裝確認方法
安裝後,可以在 Python 的互動模式(REPL)或腳本中如以下所述,來確認程式庫是否能正確匯入。import yaml
print(yaml.__version__)
如果沒有出現錯誤,則 PyYAML 已正常安裝。確認版本有助於未來的故障排除。
4. 【基本】使用 Python 讀取 YAML 檔案的方法(safe_load 的用法)
最基本的讀取方法:safe_load()
使用 PyYAML 讀取 YAML 檔案時,最常使用的函數是 safe_load()
。這個函數是為了安全讀取 YAML 而設計的函數,可以將讀取的資料取得為 Python 的字典(dict
)或列表(list
)。 首先,讓我們看看基本的 YAML 檔案及其讀取程式碼。範例 YAML 檔案(config.yaml
)
app:
name: SampleApp
version: 1.0.0
debug: true
servers:
- host: localhost
port: 8000
- host: example.com
port: 443
像這樣,包含巢狀結構或列表的 YAML 檔案,是非常適合用作設定檔案的形式。Python 中的讀取程式碼範例
使用以下程式碼,可以讀取上述的 YAML 檔案:import yaml
with open('config.yaml', 'r', encoding='utf-8') as f:
config = yaml.safe_load(f)
print(config)
輸出範例(Python 的字典形式)
{
'app': {'name': 'SampleApp', 'version': '1.0.0'},
'debug': True,
'servers': [
{'host': 'localhost', 'port': 8000},
{'host': 'example.com', 'port': 443}
]
}
像這樣,YAML 檔案可以直接作為 Python 的原生資料結構來處理,因此可以順利用於後續的處理。open()
函數中指定編碼很重要
特別是處理包含日文的 YAML 檔案時,請不要忘記在 open()
函數中encoding='utf-8'
指定。如果省略,在 Windows 環境中可能會發生文字亂碼。小提示:with
語法的活用
在讀取檔案時,像 with open(...) as f:
這樣使用with
語法,可以防止檔案關閉遺漏,並安全地進行處理。這是 Python 的最佳實踐,推薦的寫法。5. safe_load 和 load 的差異|Python 中 YAML 讀取的注意事項
safe_load()
和 load()
有什麼不同?
PyYAML 有多個用來讀取 YAML 檔案的函數,但最容易混淆的便是 safe_load()
和 load()
的差異。 乍看之下,兩者都是用來將 YAML 讀取為 Python 資料的函數,但在安全性與功能方面有很大的差異。若使用錯誤,可能會有被外部惡意 YAML 檔案執行程式碼的危險,因此理解並正確區分使用非常重要。safe_load()
的特點(安全的讀取)
import yaml
with open('config.yaml', 'r', encoding='utf-8') as f:
data = yaml.safe_load(f)
- 應使用的基本函數
- 安全性高(不讀取任意的 Python 物件)
- 限制於基本資料型(字典、列表、字串、數值等)
- 嘗試讀取未知的型別或物件時會發生錯誤
safe_load()
如其名所示,是用來進行「安全的讀取」的函數,在處理設定檔案或外部資料時,大多數情況下使用此函數是最佳選擇。load()
的特點(靈活但有風險)
import yaml
with open('config.yaml', 'r', encoding='utf-8') as f:
data = yaml.load(f, Loader=yaml.FullLoader)
- 能更靈活地解釋 YAML
- 可還原 Python 物件(例如:函數、類別實例等)
- 由於安全性風險,必須指定 Loader
事實上,在舊版的 PyYAML 中,可以單獨使用 load()
,但現在要求明確指定 Loader。若不指定任何東西使用,會發生以下類似的警告或錯誤:yaml.YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated
這是因為 load()
在過去包含了可能執行任意 Python 物件的漏洞。也就是說,若讀取不正當的 YAML 檔案,可能會無意中執行 Python 程式碼的風險。Loader 的種類(安全性和靈活性的差異)
Loader 名稱 | 特點 | 推薦度 |
---|
SafeLoader | 僅讀取基本型別(安全) | ◎ |
FullLoader | 允許更多 Python 型別(注意安全性) | ○ |
UnsafeLoader | 允許讀取任意物件(危險) | × |
結論:通常使用 safe_load()
如果您只是將 YAML 檔案作為設定檔案或外部資料讀取,那麼 safe_load()
就足夠了,而且應該使用它。load()
僅限於特殊用途(例如,想要反序列化自製的 Python 物件等情況)使用。
6. 常見錯誤及其解決方法|Python YAML 讀取的陷阱
YAML 讀取時絆倒的原因是什麼?
YAML 是一種非常簡單且易讀的格式,但因此對細微的語法規則非常嚴格。特別是在使用 Python 讀取時,新手容易忽略的一些要點。 在本節中,我們將具體介紹使用 Python 讀取 YAML 檔案時常見的錯誤、其原因以及解決方法。1. 縮排錯誤導致的語法錯誤
在 YAML 中,縮排是顯示結構的重要元素。如果空格或 Tab 不一致,讀取時就會發生錯誤。範例:有縮排錯誤的 YAML
user:
name: Alice
age: 30
錯誤訊息範例:
yaml.scanner.ScannerError: mapping values are not allowed here
解決方法:
- 以2~4 個空格統一縮排(不要使用 Tab)
- 子元素要比父元素縮排更深
2. 檔案編碼導致字元亂碼
如果 YAML 檔案包含日文等非 ASCII 字元,若不適當指定編碼,就會發生字元亂碼或解碼錯誤。錯誤範例:
UnicodeDecodeError: 'cp932' codec can't decode byte...
解決方法:
with open('config.yaml', 'r', encoding='utf-8') as f:
data = yaml.safe_load(f)
- 明確指定
encoding='utf-8'
即可解決 - 在 Windows 環境中特別容易忘記的要點
3. 檔案路徑錯誤/不存在的檔案
雖然是簡單的錯誤,但如果指定的 YAML 檔案不存在,就會發生 FileNotFoundError
。錯誤範例:
FileNotFoundError: [Errno 2] No such file or directory: 'config.yaml'
解決方法:
- 確認是否以絕對路徑或正確的相對路徑指定
- 檢查檔案名稱或副檔名是否有輸入錯誤
- 確認檔案是否位於與腳本相同的目錄
4. 使用 safe_load 讀取的結果為None
即使 YAML 的語法本身正確,如果檔案內容為空或僅有註解,也會發生這種現象。範例:
# 這個檔案中沒有任何設定
結果:
data = yaml.safe_load(f)
print(data) # 輸出: None
解決方法:
- 確認檔案中是否有記述有效的 YAML 資料
- 僅有註解或空白時,返回
None
是正常的行為
5. 過於複雜的 YAML 結構解析錯誤
在大規模且巢狀深的 YAML 檔案中,由於語法錯誤或錯誤使用錨點/別名,也可能發生錯誤。解決方法:
- 逐步確認語法(以小區段為單位驗證)
- 建議捕捉
yaml.YAMLError
例外並確認詳細訊息
try:
with open('config.yaml', 'r', encoding='utf-8') as f:
data = yaml.safe_load(f)
except yaml.YAMLError as e:
print(f"YAML 讀取錯誤: {e}")
總結:發生錯誤時不要慌張,檢查語法和環境
只要在撰寫時稍加注意,YAML 就是非常易於處理的格式。如果發生錯誤,請檢查以下要點:- 縮排是否正確(是否未使用 Tab)
- 檔案的編碼是否為 UTF-8
- 檔案是否存在
- YAML 的內容是否正確記述
7. 應用:讀取多個文件的 YAML 文件的方法(safe_load_all)
YAML 可以包含多個文件在單一文件中
YAML 的一個主要特點是,可以在一個文件中定義多個資料區塊(文件),這樣可以分割設定或配置,同時用一個檔案來統一管理。 文件之間使用 ---
(三個連字符)來明確分隔。多個文件的 YAML 檔案範例(multi.yaml)
# 伺服器設定1
---
server:
host: localhost
port: 8080
# 伺服器設定2
---
server:
host: example.com
port: 443
這樣寫的 YAML 檔案擁有兩個獨立的資料區塊,需要個別讀取每個區塊。yaml.safe_load_all()
的使用方法
在 PyYAML 中,為了讀取多個文件,準備了 safe_load_all()
函數。這是將檔案內的所有 YAML 文件作為迭代器(可迭代物件)返回的函數。import yaml
with open('multi.yaml', 'r', encoding='utf-8') as f:
documents = yaml.safe_load_all(f)
for doc in documents:
print(doc)
執行結果(輸出範例):
{'server': {'host': 'localhost', 'port': 8080}}
{'server': {'host': 'example.com', 'port': 443}}
這樣,每個文件可以作為字典逐一取得,透過迴圈處理來靈活運用。注意 safe_load()
的差異
一般的 safe_load()
只讀取第一個文件,因此不適合對應多個文件的檔案。函數名 | 對應的 YAML 格式 | 回傳值的形式 |
---|
safe_load() | 僅單一文件 | 資料(字典或列表等) |
safe_load_all() | 對應多個文件 | 迭代器(迴圈處理) |
也可以將讀取的文件轉換為列表
有時,可能想要將所有文件作為列表統一取得。在這種情況下,使用以下的 list()
即可。with open('multi.yaml', 'r', encoding='utf-8') as f:
documents = list(yaml.safe_load_all(f))
這樣,可以以列表形式批次處理,或使用索引指定來存取。注意事項:並非所有 YAML 檔案都對應多個文件
對沒有用 ---
分隔的 YAML 檔案使用 safe_load_all()
也沒有問題,但結果只會是單一文件。也就是說,safe_load_all() 是萬能的,但如果不是多個文件,就會和 safe_load() 有相同的行為,請記住這一點。
8. 【補足】使用 YAML 作為設定檔案時的要點
為什麼 YAML 適合用作設定檔案?
YAML 具備 人類易於讀寫的語法 以及 巢狀結構的靈活表現力,因此在許多專案中被採用為「設定檔案」。特別是在使用 Python 開發的應用程式或工具中,使用 YAML 可以讓 設定更容易理解,並提升維護性。 在以下用途中,YAML 非常有用:- Web 應用程式的環境設定(生產/開發/測試)
- 機器學習的超參數設定
- 腳本的行為切換
- API 金鑰等外部依賴資訊的管理(※機密資訊的管理需注意)
實用的 YAML 設定檔案範例
app:
name: MyApp
mode: production
logging:
level: INFO
file: logs/app.log
database:
host: localhost
port: 5432
user: admin
password: secret
如此一來,將構成元素依據區段彙整,任何人一看就能了解結構的設定檔案。與 JSON 不同,能自由撰寫註解的這一點在實務上也非常重要。活用巢狀結構的設定階層化
YAML 使用縮排來表現階層,因此也能直覺地表現複雜的設定。例如,想依環境區分設定時,也能如以下方式彙整:env:
dev:
db: dev-db.local
debug: true
prod:
db: prod-db.server
debug: false
在 Python 端讀取此設定,即可透過環境變數等自動選擇適當的設定。能以註解明示意圖
YAML 中可以使用 #
來撰寫註解。藉此,能將「為什麼是這樣的設定」「何時該變更」等資訊 直接記述在設定檔案內,這是很大的優點。# 應用程式的模式設定(dev, test, production 其中之一)
mode: production
JSON 中無法撰寫註解,因此有無法提供此類補充的限制。執行時讀取 YAML 的程式碼範例(應用)
以下是在 Python 腳本端讀取 YAML 設定並應用到應用程式的範例:import yaml
with open('settings.yaml', 'r', encoding='utf-8') as f:
config = yaml.safe_load(f)
app_name = config['app']['name']
mode = config['app']['mode']
db_host = config['database']['host']
如此一來,將 YAML 檔案視為 Python 的字典來處理,即可 不需在程式碼中硬編碼設定值 來進行管理。注意事項:機密資訊的處理需十分注意
YAML 雖然對人類來說易於處理,但同時也是 以明文儲存的形式。因此,在 YAML 檔案中記述 API 金鑰或密碼等機密資訊時,需要以下措施:- 使用
.gitignore
防止提交到儲存庫 - 與
.env
檔案等結合,從 YAML 只進行參照 - 套用加密或存取限制
9. 常見問題(FAQ)
在本節中,我們將以問答形式說明在 Python 中讀取 YAML 檔案時常見的疑問,以及初學者容易卡住的要點。這些內容在實際專案中使用時也很有幫助,請務必查看。Q1. YAML 和 JSON,在 Python 中哪個比較好處理?
A. YAML 可讀性高,作為設定檔案使用非常方便。 Python 中 JSON 也由標準函式庫支援,但 YAML 因為可以寫註解、結構看起來清楚等原因,在設定檔案用途上,YAML 比較好處理的感覺的人很多。不過,在重視處理速度或資料交換相容性的場合,JSON 也常被偏好。Q2. yaml.load()
不能使用嗎?
A. 原則上使用 safe_load()
比較安全。 load()
雖然彈性高,但可以還原任意的 Python 物件,因此有安全性風險。 如果讀取惡意的 YAML 檔案,可能會執行意想不到的程式碼,因此基本上推薦使用 safe_load()
。 如果有必要使用 load()
的話,請像 Loader=yaml.FullLoader
這樣明確指定,並以注重安全性的方式實作。Q3. 讀取的 YAML 內容變成空的(None)是為什麼?
A. 這是 YAML 檔案為空或只有註解時的正常動作。# 這個檔案還沒有設定
讀取上述這樣的檔案時,safe_load()
的傳回值會變成 None
。這不是異常,而是 YAML 有效的「空資料」。請確認檔案內容是否正確描述。Q4. YAML 檔案中可以像變數一樣重複使用值嗎?
A. YAML 有「錨點」和「別名」這樣的機制。default: &defaults
timeout: 30
retries: 3
service1:
<<: *defaults
host: service1.local
service2:
<<: *defaults
host: service2.local
像這樣,使用 &
來記述錨點(定義)、*
來記述別名(參照),就可以在多處重複使用相同的設定。不過,在 PyYAML 中使用這個語法時,可能需要特定版本或 Loader 設定,因此請事先確認動作。Q5. 在 Windows 環境中日文會出現亂碼。該怎麼辦?
A. 在讀取檔案時明確指定編碼即可解決。with open('config.yaml', 'r', encoding='utf-8') as f:
data = yaml.safe_load(f)
Windows 的預設文字碼(cp932
)無法正確讀取以 UTF-8 寫成的 YAML 檔案。務必明確指定 encoding='utf-8'
。Q6. 如果 YAML 檔案分成多個設定區塊要怎麼讀取?
A. 使用 safe_load_all()
就可以讀取多個文件。---
app: App1
port: 3000
---
app: App2
port: 4000
像這樣的檔案,可以用 yaml.safe_load_all()
逐一處理:with open('multi.yaml', 'r', encoding='utf-8') as f:
for doc in yaml.safe_load_all(f):
print(doc)
10. 總結|掌握Python中的YAML讀取
回顧YAML讀取從基礎到應用的內容
本文針對「想用Python讀取YAML檔案」的人,從基本用法開始,到常見錯誤的處理方法、多重文件以及作為設定檔案的應用範例,一步步詳細說明。 再次總結本文的重點:- PyYAML的安裝:要在Python中處理YAML,首先需要
pip install pyyaml
。 - 基本的讀取:
yaml.safe_load()
就能安全且簡單地將YAML讀取為字典或清單。 - 錯誤對策:縮排或編碼錯誤是常見的問題。語法檢查和
encoding='utf-8'
很重要。 load()
的差異:如果重視安全性,應該使用 safe_load()
。load()
必須指定適當的Loader。- 多重文件對應:使用
safe_load_all()
,就能靈活處理單一檔案內的多個設定區塊。 - 作為設定檔案的實用性:可讀性與彈性優異的YAML,是Python專案中的設定管理最佳選擇。
今後步驟:更多活用YAML
現在已經掌握YAML的讀取方法,下一步可以透過以下步驟,在實務中進一步活用:- 寫入YAML檔案:使用
yaml.dump()
來自動產生設定檔案 - 與JSON的相互轉換:在與Web API或外部服務聯動時很方便
- 與
.env
檔案或環境變數併用:建構高安全性的設定管理手法 - 設定的自動載入化:在應用程式啟動時,動態讀取依環境而定的設定檔案
掌握這些,就能讓使用Python的開發變得更彈性且可重複利用。 今後也會繼續以易懂的方式介紹在現場有用的Python技巧與工具的使用方法。請務必加入書籤,反覆活用。 至此,關於Python讀取YAML檔案的說明就完成了。
請習得這些在實務中也能使用的知識,並在您的專案中試著導入YAML。