In [3]:
is_colab = 'google.colab' in str(get_ipython())   # for Google Colab

if is_colab:
    from google.colab import drive
    drive.mount('/content/drive')
    DIR_PATH = '/content/drive/MyDrive/YAML/PyYAML/tutorial'
else:
    DIR_PATH = '.'
Mounted at /content/drive

PyYAML

YAML with Python

参考文献: https://python.land/data-processing/python-yaml

YAML は、人間に読みやすく、かつ、コンピュータで処理しやすいデータ・シリアライズ言語である。 区切り文字を使用することで、複数のドキュメントを1つのYAMLファイルに保存できる。

XML に似たデータ・フォーマットであるが、 YAML ではタグを使ってデータを構造化するので、 XML よりも読み書きしやすいという特徴がある。

In [1]:
# Install PyYAML
! pip install pyyaml
Requirement already satisfied: pyyaml in /usr/local/lib/python3.10/dist-packages (6.0.1)
In [2]:
# Import PyYAML
import yaml
print(yaml.__version__)
6.0.1
In [22]:
# At first, create 'config.yaml' file.
import os
path = os.path.join(DIR_PATH, 'config.yaml')

dpath, fname = os.path.split(path)
os.makedirs(dpath, exist_ok=True)

ss = """
rest:
  url: "https://example.org/primenumbers/v1"
  port: 8443

prime_numbers: [2, 3, 5, 7, 11, 13, 17, 19]
"""

with open(path, "w") as file:
    for s in ss:
        file.write(s)

YAML ファイルを Python で読み込む

YAML パーサーは、データに最適な Python オブジェクトを返す。 'config.yaml' を読み込んだ場合は Python Dictionary が返る。

In [23]:
import yaml
with open(path, 'r') as file:
    prime_service = yaml.safe_load(file)
In [24]:
print(prime_service)
{'rest': {'url': 'https://example.org/primenumbers/v1', 'port': 8443}, 'prime_numbers': [2, 3, 5, 7, 11, 13, 17, 19]}
In [25]:
print(prime_service['rest']['url'])
https://example.org/primenumbers/v1

YAML 文字の解析

yaml.save_load() 関数を使うと、あらゆる種類の YAML 文字列を解析できる。

In [26]:
# (例) 単純なアイテムのリストを解析して、Python リストを返す

import yaml
names_yaml = """
- 'eric'
- 'justin'
- 'mary-kate'
"""

names = yaml.safe_load(names_yaml)
print(names)
['eric', 'justin', 'mary-kate']

複数の YAML ドキュメントを含むファイルの解析

In [30]:
# まず、解析対称のファイルを作成しておく

import os
path = os.path.join(DIR_PATH, 'multi_doc.yml')

dpath, fname = os.path.split(path)
os.makedirs(dpath, exist_ok=True)

ss = """
document: 1
name: 'erik'
---
document: 2
name: 'config'
"""

with open(path, "w") as file:
    file.write(ss)
In [31]:
# 複数の YAML ファイルを含むドキュメントを読み込む
import yaml

with open(path, 'r') as file:
    docs = yaml.safe_load_all(file)
    for doc in docs:
        print(doc)
{'document': 1, 'name': 'erik'}
{'document': 2, 'name': 'config'}

YAML をファイルに書き込む

In [34]:
# write-yaml.py
import yaml

names_yaml = """
- 'eric'
- 'justin'
- 'mary-kate'
"""

names = yaml.safe_load(names_yaml)

path = os.path.join(DIR_PATH, 'names.yaml')
dpath, fname = os.path.split(path)
os.makedirs(dpath, exist_ok=True)

with open(path, "w") as file:
    yaml.dump(names, file)
In [35]:
print(open(path).read())
- eric
- justin
- mary-kate

In [36]:
! cat {path}
- eric
- justin
- mary-kate

Python を用いて YAML を JSON に変換する

In [41]:
import os
path = os.path.join(DIR_PATH, 'config.yaml')
json_path = os.path.join(DIR_PATH, 'config.json')

import yaml
import json

with open(path, 'r') as file:
    configuration = yaml.safe_load(file)

with open(json_path, 'w') as json_file:
    json.dump(configuration, json_file)
In [42]:
! cat {json_path}
{"prime_numbers": [2, 3, 5, 7, 11, 13, 17, 19], "rest": {"port": 8443, "url": "https://example.org/primenumbers/v1"}}
In [43]:
output = json.dumps(json.load(open(json_path)), indent=2)
print(output)
{
  "prime_numbers": [
    2,
    3,
    5,
    7,
    11,
    13,
    17,
    19
  ],
  "rest": {
    "port": 8443,
    "url": "https://example.org/primenumbers/v1"
  }
}

JSON を YAML に変換する

In [39]:
import yaml
import json

with open(json_path, 'r') as file:
    configuration = json.load(file)

with open(path, 'w') as yaml_file:
    yaml.dump(configuration, yaml_file)
In [45]:
! cat {path}
prime_numbers:
- 2
- 3
- 5
- 7
- 11
- 13
- 17
- 19
rest:
  port: 8443
  url: https://example.org/primenumbers/v1
In [46]:
with open(path, 'r') as yaml_file:
    print(yaml_file.read())
prime_numbers:
- 2
- 3
- 5
- 7
- 11
- 13
- 17
- 19
rest:
  port: 8443
  url: https://example.org/primenumbers/v1

Python の load() 対 PyYAML の safe_load()

PYthon の load() 関数は、python のコードを何でも実行できてしまうので危険であり、現在は非推奨になっている。 そのため、比較的安全と考えられる PyYAML の safe_load() を使うべきである。

In [ ]: