Last Updated on 2021-09-19 by Clay
曾經我以為,使用 Json 當作設定檔的格式幾乎可以滿足我所有的要求,但實際上,若是以『需要人工修改設定檔』的角度來看,Json 格式並一定是容易閱讀的。
想來想去,我終於有點明白為什麼以前在看他人的專案時,會看到有些人是使用 YAML 格式的檔案來儲存程式的設定了。以讓人工修改設定的角度來看,YAML 格式確實更易讀取。
於是乎,就有了我今天想要紀錄的這篇文章、關於 YAML 格式的檔案讀寫。
YAML 格式是什麼?
根據 Wiki 的介紹,YAML 是一種序列化資料的格式,而所謂的序列化(serialization)資料,則是指能夠快速地將『資料結構』或是『物件』轉換成『可使用格式』的一種資料的稱呼。
用最最白話的方式來說,YAML 就是一種很方便的格式,可以使用純文字檔儲存,快速地讓程式讀取,並轉化成特定的資料型態。
順帶一提,將資料轉成 YAML 格式寫入這一過程通常稱為『序列化』,而反過來將 YAML 格式讀取成程式內的物件則被稱為『反序列化』。
而為什麼我上面我會說想要使用 YAML 來儲存程式的設定、而非使用 Json 呢?
簡單來講,假設我底下有這樣一筆的資料(以 Python 的 Dict 儲存):
{
'2020-10-30': {'name': 'Use Python to copy pictures to the clipboard',
'update_date': '2020-11-01',
'url': 'https://clay-atlas.com/us/blog/2020/10/30/python-en-pillow-screenshot-copy-clipboard/'},
'2020-11-04': {'name': 'Use Python PyInstaller to make an executable file with picture',
'update_date': '2020-11-7',
'url': 'https://clay-atlas.com/us/blog/2020/11/04/python-en-package-pyinstaller-picture/'}
}
可以看到,這是我部落格文章的紀錄,以撰寫日期作為 key 值,儲存著上傳網址、文章標題、最後更新日期等三個屬性。
在 YAML 格式儲存的屬性中,顯示非常乾淨:
'2020-10-30': name: Use Python to copy pictures to the clipboard update_date: '2020-11-01' url: https://clay-atlas.com/us/blog/2020/10/30/python-en-pillow-screenshot-copy-clipboard/ '2020-11-04': name: Use Python PyInstaller to make an executable file with picture update_date: '2020-11-7' url: https://clay-atlas.com/us/blog/2020/11/04/python-en-package-pyinstaller-picture/
反之,Json 儲存的檔案又如何呢?以下則是 Json 儲存的檔案:
{"2020-11-04": {"url": "https://clay-atlas.com/us/blog/2020/11/04/python-en-package-pyinstaller-picture/", "name": "Use Python PyInstaller to make an executable file with picture", "update_date": "2020-11-7"}, "2020-10-30": {"url": "https://clay-atlas.com/us/blog/2020/10/30/python-en-pillow-screenshot-copy-clipboard/", "name": "Use Python to copy pictures to the clipboard", "update_date": "2020-11-01"}}
是的,我沒有改動!預設的儲存格式就是一整行 ......
雖然好像不是沒有方法可以漂亮地顯示,但是我覺得使用 YAML 格式就很漂亮了!也方便人工修改參數。
使用 PyYAML 讀寫 YAML 格式的檔案
接下來就進入本文的重點了:如何讀寫 YAML 檔案呢?首先,Python 中似乎有滿多套件可以實現 YAML 檔案的讀寫的,在這裡我推薦使用 PyYAML 這一套件。(雖然,你也可以自己寫一個解析器來辦到就是了。)
首先,使用以下指令安裝 PyYAML 套件。
pip3 install pyyaml
安裝好後,首先來看看該怎麼透過 pyyaml 儲存資料吧!
寫入 YAML 格式檔案
以下是個簡單的範例檔案,data 儲存的分別是『家中』與『辦公室』的動物數量資料。
家裡養了很簡單的一狗兩貓、辦公室養滿了海鮮(?)
# coding: utf-8 import yaml def main(): # Data data = { 'home': { 'pets': ['dog', 'cat', 'cat'], 'numbers': 3, }, 'office': { 'pets': ['fish', 'crab', 'shrimp'], 'numbers': 3, } } # Save with open('example.yml', 'w') as f: yaml.dump(data, f, Dumper=yaml.CDumper) if __name__ == '__main__': main()
儲存方法的接口看起來跟 Json 套件的設計一模一樣,這樣實在很好,可以舒服地記下不同套件之間的儲存方法。
接下來我們打開儲存的 example.yml 檔案看看:
home: numbers: 3 pets: - dog - cat - cat office: numbers: 3 pets: - fish - crab - shrimp
相當好懂!人工修改也方便。
讀取 YAML 格式檔案
那麼接下來就進入讀取的部分了。
# coding: utf-8 import yaml from pprint import pprint def main(): with open('example.yml', 'r') as stream: data = yaml.load(stream, Loader=yaml.CLoader) pprint(data) if __name__ == '__main__': main()
Output:
{'home': {'numbers': 3, 'pets': ['dog', 'cat', 'cat']},
'office': {'numbers': 3, 'pets': ['fish', 'crab', 'shrimp']}}
就是這麼簡單。我想,我以後會把許多需要自己修改的參數檔案都調整為以 YAML 格式的檔案處存的。
References
- https://github.com/yaml/pyyaml
- https://pypi.org/project/PyYAML/
- https://stackabuse.com/reading-and-writing-yaml-to-a-file-in-python/
- https://stackoverflow.com/questions/1773805/how-can-i-parse-a-yaml-file-in-python