Python 3.11で追加されたtomlibを使ってみる

2023.08.02

データアナリティクス事業本部のueharaです。

今回は、Python 3.11で追加されたtomlibを使ってみたいと思います。

tomlibとは

Python 3.11で追加されたTOML(Tom's Obvious Minimal Language)を解析するための標準モジュールです。

このモジュールではTOMLの書き出しはサポートされておらず、あくまでパース用のモジュールになります。

TOMLについて知りたい方は以下をご確認ください。

環境構築

平素使っているPythonの実行環境に影響を与えたくないので、dockerでPython 3.11の実行環境を構築します。

準備するフォルダ構成は以下の通りです。

.
├ compose.yml
└ scripts
  ├ test.py
  └ data.toml

compose.ymlの記載

compose.ymlを、以下のように記載します。

compose.yml

services:
  python311:
    container_name: python311
    image: python:3.11.4-bookworm
    working_dir: /root/scripts
    volumes:
      - ./scripts:/root/scripts
    tty: true

compose.ymlファイルと同じ階層に作成したscriptsフォルダをコンテナ側の/root/scriptsにマウントし、作業用ディレクトリに指定しています。

起動と接続

compose.ymlの準備が完了したら、コンテナの起動と接続を行います。

# コンテナの起動
$ docker compose up -d 

# コンテナへの接続(bashの起動)
$ docker compose exec python311 bash

以下のように接続でき、コマンドが実行できれば成功です。

tomlibを使ってみる

TOMLとPythonの対応表は以下の通りです。

TOML Python
table dict
string str
integer int
float float (configurable with parse_float)
boolean bool
offset date-time datetime.datetime (tzinfo attribute set to an instance of datetime.timezone)
local date-time datetime.datetime (tzinfo attribute set to None)
local date datetime.date
local time datetime.time
array list

また、tomlibにはTOML形式のデータを読み込むのにファイルからの読み込み文字列からの読み込みがあります。

ファイルからの読み込み

tomllib.load関数でTOMLファイルを読み込むことができます。

テスト用のTOMLファイルはとりあえず網羅的に以下のようにしてみました。(テーブルを正しく認識させるには、テーブルデータを末尾にもっていく必要があります)

data.toml

# string
data01 = "hoge"

# integer
data02 = 10

# float
data03 = 1.23

# boolean
data04 = true

# offset date-time
data05 = 2023-08-02T07:32:00+09:00

# local date-time
data06 = 2023-08-02T07:32:00

# local date
data07 = 2023-08-02

# local time
data08 = 07:32:00

# array
data09 = [1, 2, 3, 4, 5]

# table
[data10]
key1 = "foo"
key2 = 123

test.py

import tomllib
import pprint


with open("data.toml", "rb") as f:
    data = tomllib.load(f)
    pprint.pprint(data)
    pprint.pprint([type(v) for v in data.values()])

実行結果は以下の通りです。

$ python test.py
{'data01': 'hoge',
 'data02': 10,
 'data03': 1.23,
 'data04': True,
 'data05': datetime.datetime(2023, 8, 2, 7, 32, tzinfo=datetime.timezone(datetime.timedelta(seconds=32400))),
 'data06': datetime.datetime(2023, 8, 2, 7, 32),
 'data07': datetime.date(2023, 8, 2),
 'data08': datetime.time(7, 32),
 'data09': [1, 2, 3, 4, 5],
 'data10': {'key1': 'foo', 'key2': 123}}
[<class 'str'>,
 <class 'int'>,
 <class 'float'>,
 <class 'bool'>,
 <class 'datetime.datetime'>,
 <class 'datetime.datetime'>,
 <class 'datetime.date'>,
 <class 'datetime.time'>,
 <class 'list'>,
 <class 'dict'>]

本章の冒頭で示したテーブル通りのマッピングになっていることが分かります。

※例:TOMLのオフセット付日時 2023-08-02T07:32:00+09:00 が Pythonのtzinfoが設定されたdatetime datetime.datetime(2023, 8, 2, 7, 32, tzinfo=datetime.timezone(datetime.timedelta(seconds=32400))) になっている。

文字列からの読み込み

tomllib.loads関数で文字列のTOML形式を読み込むことができます。

test.py

import tomllib


toml_str = """
python-version = "3.11.0"
python-implementation = "CPython"
"""

data = tomllib.loads(toml_str)
print(data)

実行結果は以下の通りです。

$ python test.py
{'python-implementation': 'CPython', 'python-version': '3.11.0'}

float型のパースについて

また、floatについては、tomllib.load, tomllib.loads関数共にparse_float引数に別のデータ型を渡すことができます。(デフォルトはfloat

test.py

import decimal
import tomllib


toml_str = """
data01 = 1.23
data02 = 0.99999999999999999
"""

data = tomllib.loads(toml_str, parse_float=decimal.Decimal)
print(data)
print([type(v) for v in data.values()])

decimal.Decimalを渡した場合、実行結果は以下の通りです。

$ python test.py
{'data01': Decimal('1.23'), 'data02': Decimal('0.99999999999999999')}
[<class 'decimal.Decimal'>, <class 'decimal.Decimal'>]

最後に

今回は、Python 3.11で追加されたtomlibを使ってみました。

参考になりましたら幸いです。

参考文献