Skip to content

[Python] 使用 PyYAML 讀取 YAML 格式的檔案

Last Updated on 2021-09-19 by Clay

曾經我以為,使用 Json 當作設定檔的格式幾乎可以滿足我所有的要求,但實際上,若是以『需要人工修改設定檔』的角度來看,Json 格式並一定是容易閱讀的。

想來想去,我終於有點明白為什麼以前在看他人的專案時,會看到有些人是使用 YAML 格式的檔案來儲存程式的設定了。以讓人工修改設定的角度來看,YAML 格式確實更易讀取。

於是乎,就有了我今天想要紀錄的這篇文章、關於 YAML 格式的檔案讀寫。


YAML 格式是什麼?

根據 Wiki 的介紹,YAML 是一種序列化資料的格式,而所謂的序列化(serialization)資料,則是指能夠快速地將『資料結構』或是『物件』轉換成『可使用格式』的一種資料的稱呼。

用最最白話的方式來說,YAML 就是一種很方便的格式,可以使用純文字檔儲存,快速地讓程式讀取,並轉化成特定的資料型態。

順帶一提,將資料轉成 YAML 格式寫入這一過程通常稱為『序列化』,而反過來將 YAML 格式讀取成程式內的物件則被稱為『反序列化』。

而為什麼我上面我會說想要使用 YAML 來儲存程式的設定、而非使用 Json 呢?

簡單來講,假設我底下有這樣一筆的資料(以 PythonDict 儲存):

{
'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


Read More

Leave a Reply