Python 資料處理:CSV、JSON、XML 與 YAML 完全指南
簡介
在日常開發與資料分析的工作中,資料交換格式是不可或缺的橋樑。
CSV、JSON、XML、YAML 四大格式各有特點,從簡單的表格資料到階層式結構、再到可讀性極佳的設定檔,都常在 Python 專案裡交替使用。
掌握它們的讀寫方法,不只可以讓程式與外部系統順利溝通,也能大幅提升資料前處理與自動化腳本的效率。
本篇文章以 Python 3 為例,從概念說明、實作範例、常見陷阱到最佳實踐,帶你一步步完成 CSV、JSON、XML、YAML 的完整操作,適合剛踏入程式設計的初學者,也能為中階開發者提供實務參考。
核心概念
1. CSV(Comma‑Separated Values)
CSV 是最傳統的表格資料格式,每一列代表一筆紀錄,欄位以逗號(或其他分隔符)分隔。
Python 內建的 csv 模組提供讀寫支援,且支援自訂分隔符、編碼與換行處理。
1.1 讀取 CSV
import csv
# 讀取檔案時使用 utf-8-sig 以正確處理 BOM
with open('data.csv', newline='', encoding='utf-8-sig') as f:
reader = csv.DictReader(f) # 以欄位名稱建立 dict
for row in reader:
# row 為 {'name': 'Alice', 'age': '30', ...}
print(row['name'], int(row['age']))
1.2 寫入 CSV
import csv
data = [
{'name': 'Bob', 'age': 25, 'city': 'Taipei'},
{'name': 'Carol', 'age': 28, 'city': 'Kaohsiung'}
]
with open('out.csv', mode='w', newline='', encoding='utf-8') as f:
fieldnames = ['name', 'age', 'city']
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader() # 寫入欄位名稱
writer.writerows(data) # 一次寫入多筆
2. JSON(JavaScript Object Notation)
JSON 是現代 Web API 的事實標準,以鍵值對的形式表達資料,支援巢狀結構。
Python 的 json 模組提供序列化(dump/dumps)與反序列化(load/loads)功能。
2.1 讀取 JSON
import json
with open('config.json', encoding='utf-8') as f:
config = json.load(f) # 直接得到 dict / list
# 取得嵌套值
db_host = config['database']['host']
print(f"DB Host: {db_host}")
2.2 寫入 JSON(美化輸出)
import json
result = {
'status': 'ok',
'data': [1, 2, 3, 4],
'message': None
}
with open('result.json', mode='w', encoding='utf-8') as f:
json.dump(result, f, ensure_ascii=False, indent=4)
# ensure_ascii=False 讓中文直接顯示,indent=4 美化排版
2.3 處理非 UTF‑8 編碼的 JSON
import json
# 若檔案是 big5 編碼,需要先 decode 後再 load
with open('big5.json', 'rb') as f:
raw = f.read()
text = raw.decode('big5')
data = json.loads(text)
3. XML(eXtensible Markup Language)
XML 以樹狀結構描述資料,常見於 舊系統、設定檔或大型企業資料交換。
Python 有 xml.etree.ElementTree(簡易)與 lxml(功能完整)兩種常用套件。
3.1 讀取 XML(ElementTree)
import xml.etree.ElementTree as ET
tree = ET.parse('books.xml')
root = tree.getroot() # <catalog>
for book in root.findall('book'):
title = book.find('title').text
price = float(book.find('price').text)
print(f"{title}: ${price:.2f}")
3.2 建立 XML 並寫入檔案
import xml.etree.ElementTree as ET
root = ET.Element('people')
person = ET.SubElement(root, 'person', attrib={'id': '001'})
ET.SubElement(person, 'name').text = 'David'
ET.SubElement(person, 'age').text = '34'
tree = ET.ElementTree(root)
tree.write('people.xml', encoding='utf-8', xml_declaration=True)
3.3 使用 lxml 取得 XPath
from lxml import etree
doc = etree.parse('books.xml')
# 取得所有價格大於 30 的書名
titles = doc.xpath('//book[price>30]/title/text()')
print(titles)
4. YAML(YAML Ain't Markup Language)
YAML 強調 可讀性與直觀的縮排結構,常用於設定檔(如 Docker Compose、GitHub Actions)或資料序列化。
Python 主要使用 PyYAML 套件。
4.1 讀取 YAML
import yaml
with open('settings.yaml', encoding='utf-8') as f:
cfg = yaml.safe_load(f) # 只允許安全類型
print(cfg['server']['port'])
4.2 寫入 YAML(保留順序)
import yaml
from collections import OrderedDict
data = OrderedDict([
('name', 'Eve'),
('roles', ['admin', 'user']),
('active', True)
])
with open('user.yaml', 'w', encoding='utf-8') as f:
yaml.dump(data, f, allow_unicode=True, sort_keys=False)
4.3 讀寫多文件(--- 分隔)
import yaml
multi_doc = """
---
name: Alice
age: 30
---
name: Bob
age: 25
"""
docs = list(yaml.safe_load_all(multi_doc))
for d in docs:
print(d['name'], d['age'])
常見陷阱與最佳實踐
| 格式 | 常見錯誤 | 建議的最佳實踐 |
|---|---|---|
| CSV | 逗號未被正確轉義,導致欄位錯位。 | 使用 csv 模組的 quotechar 與 quoting=csv.QUOTE_MINIMAL,或改用 pandas.read_csv 處理大型檔案。 |
| JSON | NaN、Infinity 會在 json.dump 時拋錯。 |
先將非 JSON 可序列化的值轉為 null 或字串,或使用 json.dumps(..., allow_nan=False) 捕捉例外。 |
| XML | 命名空間(namespace)未處理,XPath 失效。 | 使用 ElementTree.register_namespace 或在 lxml 中加入 nsmap,統一管理前綴。 |
| YAML | 不安全的 yaml.load 可能執行任意程式碼。 |
永遠使用 yaml.safe_load,若需要自訂類別,使用 yaml.FullLoader 並明確註冊。 |
| 共通 | 編碼不一致(UTF‑8、Big5、UTF‑16)導致讀取失敗。 | 開檔時明確指定 encoding,必要時先偵測檔案編碼(如 chardet 套件)。 |
其他實用技巧
- 使用
Path(pathlib) 替代字串路徑,提高跨平台相容性。 - 大量資料時考慮流式處理(
csv.reader逐行、json.load逐物件、iterparse解析 XML)。 - 加入型別檢查(
pydantic、dataclasses)讓資料結構更安全、易於除錯。
實際應用場景
資料匯入與匯出:
- 從舊系統匯出 CSV,使用
pandas轉為 DataFrame,清洗後再寫入 JSON 供前端 API 使用。
- 從舊系統匯出 CSV,使用
設定與部署:
- 使用 YAML 撰寫 CI/CD 工作流程(GitHub Actions),在部署腳本中讀取 JSON API 回傳的設定,動態生成 Docker Compose 檔案。
跨系統整合:
- 與第三方 ERP 系統交換 XML 報表,利用
lxml的 XPath 快速抽取關鍵欄位,轉存為 CSV 供業務分析。
- 與第三方 ERP 系統交換 XML 報表,利用
日誌與監控:
- 將應用程式的錯誤訊息以 JSON 格式寫入 log,並以 Python 定時任務(
schedule)將每日 log 轉換成 CSV,供 Excel 報表使用。
- 將應用程式的錯誤訊息以 JSON 格式寫入 log,並以 Python 定時任務(
總結
- CSV 適合簡單表格資料,使用
csv模組可避免欄位錯位與編碼問題。 - JSON 是 Web API 的首選,務必注意 UTF‑8、
null與非標準數值的處理。 - XML 雖然較為冗長,但在企業級資料交換仍佔一席之地,
ElementTree為入門,lxml為進階。 - YAML 以可讀性見長,適合設定檔與多文件序列化,務必使用
safe_load以免安全風險。
掌握上述四種格式的讀寫技巧,並結合 編碼統一、流式處理與型別驗證 的最佳實踐,能讓你的 Python 資料處理工作更加穩定、可維護且高效。未來在面對不同系統、不同需求時,只要選對工具、寫對程式,就能輕鬆完成資料的轉換與搬運。祝你在 Python 的資料處理之路上越走越遠!