ホームページ  >  記事  >  バックエンド開発  >  Python を使用して toml 構成ファイルを解析する方法

Python を使用して toml 構成ファイルを解析する方法

王林
王林転載
2023-05-21 11:20:041228ブラウズ

例を示します

ini と yaml を使用すると、toml も非常に簡単に学習できると思います。例を直接見てみましょう。

import toml

config = """
title = "toml 小栗子"

[owner]
name = "古明地觉"
age = 17
place = "东方地灵殿"
nickname = ["小五", "少女觉", "觉大人"]

[database]
host = "127.0.0.1"
port = 5432
username = "satori"
password = "123456"
echo = true

[server]
    [server.v1]
    api = "1.1"
    enable = false
    
    [server.v2]
    api = "1.2"
    enable = true

[client]
client = [
    ["socket", "webservice"], 
    [5555]
]
address = [
    "xxxx",
    "yyyy"
]
"""

# loads:从字符串加载
# load:从文件加载
# dumps:生成 toml 格式字符串
# dump:生成 toml 格式字符串并写入文件中
data = toml.loads(config)
print(data)
"""
{
    'title': 'toml 小栗子', 
    'owner': {'name': '古明地觉', 
              'age': 17, 
              'place': '东方地灵殿', 
              'nickname': ['小五', '少女觉', '觉大人']},
    'database': {'host': '127.0.0.1', 
                 'port': 5432,
                 'username': 'satori', 
                 'password': '123456', 
                 'echo': True},
    'server': {'v1': {'api': '1.1', 'enable': False}, 
               'v2': {'api': '1.2', 'enable': True}},
    'client': {'client': [['socket', 'webservice'], [5555]], 
               'address': ['xxxx', 'yyyy']}
}
"""

tomlはvar = valueという形で構成されており、iniと同様のセクションもあり、各セクションが辞書のキーになっており、キーも辞書に対応しています。セクションがないため、最初のタイトルに注意する必要があるため、別のキーになっています。

もう 1 つの点は、toml がネストをサポートしていることです。server.v1 が表示されます。これは、v1 がサーバーに対応するディクショナリ内のキーであり、v1 に対応する値が依然としてディクショナリであることを意味します。

toml はよりシンプルになり、Python によく似て記述されています。次の特徴があります:

toml ファイルは大文字と小文字が区別されます。

toml ファイルは有効である必要があります。 UTF-8 でエンコードされた Unicode ドキュメント;

toml ファイルの空白文字はタブまたはスペースである必要があります;

toml ファイルの改行は LF または CRLF である必要があります;

それではtomlのデータ構造を紹介していきます。

Comments

toml は # を使用してコメントを表します。例:

# 这是注释
key = "value"  # 也是注释

これを解析して、何が得られるかを確認できます。スポイラー: 取得できるキーは 1 つだけです。値ペアの辞書。

キーと値のペア

基本ブロックはキーと値のペアであり、等号の左側にキー名、右側に値があり、空白は無視されます。キー名とキー値に関する TOML ドキュメント。さらに、キー、等号、値は同じ行になければなりません (ただし、値によっては複数行にまたがることもできます)。

key = "value"

キー名は、裸のキー、引用符で囲まれたキー、またはドット区切りのキーの形式で表示されます。ベアキーには、ASCII 文字、数字、アンダースコア、およびハイフンのみを含めることができます。

import toml

config = """
key = "value"
bare_key = "value"
bare-key = "value"
# 1234 会被当成字符串
1234 = "value"  
"""

data = toml.loads(config)
print(data)
"""
{'key': 'value', 
 'bare_key': 'value', 
 'bare-key': 'value', 
 '1234': 'value'}
"""

ベア キーでない場合は、引用符で囲む必要があります。ただし、現時点では、より広範囲のキー名の使用もサポートされていますが、特別なシナリオを除いて、ベア キーの使用は困難です。ベストプラクティス。

import toml

config = """
"127.0.0.1" = "value"
"character encoding" = "value"
"ʎǝʞ" = "value"
'key2' = "value"
'quoted "value"' = "value" 
"""

data = toml.loads(config)
print(data)
"""
{'127.0.0.1': 'value', 
 'character encoding': 'value', 
 'ʎǝʞ': 'value', 
 'key2': 'value', 
 'quoted "value"': 'value'}
"""

注: 裸のキーを空にすることはできませんが、空の引用符キーは許可されます (ただし、推奨されません)。

= "没有键名"  # 错误
"" = "空"     # 正确但不鼓励
'' = '空'     # 正确但不鼓励

次に、ドットで区切られたキーがあります。これは、ドットで接続された一連のベア キーまたは引用符で囲まれたキーであり、同様の属性をまとめることができます。

import toml

config = """
name = "橙子"
physical.color = "橙色"
physical.shape = "圆形"
site."google.com" = true
site.google.com = true
a.b.c.d = 123
"""

data = toml.loads(config)
print(data)
"""
{
    'name': '橙子',
    'physical': {'color': '橙色',
                 'shape': '圆形'},
    'site': {'google.com': True,
             'google': {'com': True}},
    'a': {'b': {'c': {'d': 123}}}
}
"""

このドットが表示されます。 -分離キー 文字は適切で、入れ子構造が自動的に実装され、ドット区切り文字の周囲の空白は無視されます。

fruit.name = "香蕉"     # 这是最佳实践
fruit. color = "黄色"    # 等同于 fruit.color
fruit . flavor = "香蕉"   # 等同于 fruit.flavor

注: 同じキーを複数回定義することはできません。

import toml

config = """
# name 和 "name" 是等价的
name = "古明地觉"
"name" = "古明地恋"  
"""

try:
    data = toml.loads(config)
except toml.decoder.TomlDecodeError as e:
    print(e)
"""
Duplicate keys! (line 4 column 1 char 36)
"""

同じことがドット区切りキーにも当てはまります。キーが直接定義されていない限り、キーとその下位キー名に値を割り当てることができます。

import toml

config = """
fruit.apple.smooth = true# 此时可以继续操作 fruit、fruit.apple,它们都是字典
# 给 fruit 这个字典加一个 key  
fruit.orange = 2  
# 给 fruit.apple 加一个 key
fruit.apple.color = "red"   
"""

data = toml.loads(config)
print(data)
"""
{
    'fruit': {'apple': {'smooth': True, 
                        'color': 'red'}, 
              'orange': 2}
}
"""

ただし、次の操作は実行できません:

# 将 fruit.apple 的值定义为一个整数
fruit.apple = 1
# 但接下来就不合法了,因为整数不能变成字典
fruit.apple.smooth = true

# 如果我们设置 fruit.apple = {},那么第二个赋值是可以的
# 没错,我们可以通过 {} 直接创建一个字典

ご覧のとおり、これは本当に Python に似ています。次に、特殊なケースについて説明します。

import toml

config = """
3.14 = "pi"  
"3.14" = "pi"  
"""

data = toml.loads(config)
print(data)
"""
{'3': {'14': 'pi'}, '3.14': 'pi'}
"""

キーが浮動小数点数の場合は、引用符で囲む必要があります。そうでない場合は、ドット区切りのキーとして解釈されます。

キーを読んだ後、値を見てみましょう。実際、toml の場合、値はキーよりもはるかに単純です。

文字列

文字列を表現するには、基本、複数行の基本、リテラル、および複数行リテラルの 4 つの方法があります。

1) 基本文字列は引用符で囲まれており、エスケープする必要がある文字を除く任意の Unicode 文字を使用できます。

import toml

config = """
str = '我是一个字符串,"你可以把我引起来"' 
"""

data = toml.loads(config)
print(data)
"""
{'str': '我是一个字符串,"你可以把我引起来"'}
"""

複数行の文字列は 3 つの引用符で囲み、改行を含めることができます。ただし、開始引用符の後の最初の改行は削除され、他のスペースと改行は保持されることに注意してください。

import toml

config = """
str = '''
玫瑰是红色的
紫罗兰是蓝色的
'''
"""

data = toml.loads(config)
print(data)
"""
{'str': '玫瑰是红色的\n紫罗兰是蓝色的\n'}
"""

ここでの引用符は二重引用符でも一重引用符でもかまいません。

整数

整数は純粋な数値です。正の数値にはプラス記号を接頭辞として付けることができ、負の数値にはマイナス記号を接頭辞として付けることができます。

import toml

config = """
int1 = +99
int2 = 42
int3 = 0
int4 = -17

# 对于大数,可以在数字之间用下划线来增强可读性
# 每个下划线两侧必须至少有一个数字。
int5 = 1_000
int6 = 5_349_221
int7 = 53_49_221  # 印度记数体系分组
int8 = 1_2_3_4_5  # 无误但不鼓励
"""

data = toml.loads(config)
print(data)
"""
{'int1': 99,
 'int2': 42,
 'int3': 0,
 'int4': -17,
 'int5': 1000,
 'int6': 5349221,
 'int7': 5349221,
 'int8': 12345}
"""

ただし、注意: 0 自体を除き、数字をゼロで始めることはできません。接頭辞のないゼロ、-0、および 0 は同等です。負でない整数値は、16 進数、8 進数、または 2 進数で表すこともできます。

# 带有 `0x` 前缀的十六进制,大小写均可
hex1 = 0xDEADBEEF
hex2 = 0xdeadbeef
hex3 = 0xdead_beef

# 带有 `0o` 前缀的八进制
oct1 = 0o01234567
oct2 = 0o755 # 对于表示 Unix 文件权限很有用

# 带有 `0b` 前缀的二进制
bin1 = 0b11010110

浮動小数点数

浮動小数点数は、整数部と小数部で構成することも、指数部で構成することもできます。整数部分と小数部分は、10 進整数値の場合と同じ規則に従います。小数部と指数部の両方がある場合は、小数部を指数部の前に置く必要があります。

import toml

config = """
# 小数
flt1 = +1.0
flt2 = 3.1415
flt3 = -0.01

# 指数
flt4 = 5e+22
flt5 = 1e06
flt6 = -2E-2

flt7 = 6.626e-34
"""

data = toml.loads(config)
print(data)
"""
{'flt1': 1.0,
 'flt2': 3.1415,
 'flt3': -0.01,
 'flt4': 5e+22,
 'flt5': 1000000.0,
 'flt6': -0.02,
 'flt7': 6.626e-34}
"""

小数部は小数点の後に 1 つ以上の数字が続き、指数部は E (大文字または小文字) の後に整数部が続きます (10 進整数値と同じ規則に従います)。ただし、先頭にゼロを含めることはできます)。小数点を使用する場合は、両側の少なくとも 1 桁のすぐ隣になければなりません。

# 非法的浮点数
invalid_float_1 = .7
invalid_float_2 = 7.
invalid_float_3 = 3.e+20

整数と同様に、アンダースコアを使用すると読みやすくなります。各アンダースコアは少なくとも 1 つの数字で囲む必要があります。

flt8 = 224_617.445_991_228

浮動小数点値 -0.0 および 0.0 は有効であり、IEEE 754 に準拠する必要があります。特別な浮動小数点値も表すことができます:

# 无穷
sf1 = inf  # 正无穷
sf2 = +inf # 正无穷
sf3 = -inf # 负无穷

# 非数
sf4 = nan  # 是对应信号非数码还是静默非数码,取决于实现
sf5 = +nan # 等同于 `nan`
sf6 = -nan # 正确,实际码取决于实现

ブール値

ブール値はそれと同じですが、小文字になります。

bool1 = true
bool2 = false

Date

通常の日時、または ISO-8859-1 形式に従った日付を指定できます。

import toml

config = """
dt1 = 2020-01-01T12:33:22+00:00
dt2 = 2020-11-12 12:11:33
dt3 = 2020-11-23
"""

data = toml.loads(config)
print(data)
"""
{'dt1': datetime.datetime(2020, 1, 1, 12, 33, 22, tzinfo=...), 
 'dt2': datetime.datetime(2020, 11, 12, 12, 11, 33), 
 'dt3': datetime.date(2020, 11, 23)}
"""

Array

構文は Python のリストに似ています:

import toml

config = """
# 每个数组里面的元素类型要一致
integers = [1, 2, 3]
colors = ["红", "黄", "绿"]
nested_array_of_ints = [[1, 2], [3, 4, 5]]
nested_mixed_array = [[1, 2], ["a", "b", "c"]]
numbers = [0.1, 0.2, 0.5]
"""

data = toml.loads(config)
print(data)
"""
{'colors': ['红', '黄', '绿'],
 'integers': [1, 2, 3],
 'nested_array_of_ints': [[1, 2], [3, 4, 5]],
 'nested_mixed_array': [[1, 2], ['a', 'b', 'c']],
 'numbers': [0.1, 0.2, 0.5]}
"""

配列は複数行にまたがることができ、その後に終端コンマ (末尾コンマとも呼ばれます) を置くことができます。配列の最後の値。

import toml

config = """
integers2 = [
  1, 2, 3
]

integers3 = [
  1,
  2, # 这是可以的
]
"""

data = toml.loads(config)
print(data)
"""
{'integers2': [1, 2, 3], 'integers3': [1, 2]}
"""

Table

テーブルは、ini のセクションとして考えることができます。

import toml

config = """
# 表名的定义规则与键名相同
# 解析之后得到的大字典中就有 "table-1" 这个 key
# 并且其 value 也是一个表,在它下方
# 直至下一个表头或文件结束,都是这个表内部的键值对
[table-1]
key1 = "some string"
key2 = 123

[table-2]
key1 = "another string"
key2 = 456
"""

data = toml.loads(config)
print(data)
"""
{'table-1': {'key1': 'some string', 'key2': 123},
 'table-2': {'key1': 'another string', 'key2': 456}}
"""

しかし、これに似た構造を以前に実装しました。はい、それはドット区切り文字です:

import toml

config = """
# 所以 other-table-1 和 table-1 是等价的
# other-table-2 和 table-2 是等价的
other-table-1.key1 = "some string"
other-table-1.key2 = 123

other-table-2.key1 = "another string"
other-table-2.key2 = 456

[table-1]
key1 = "some string"
key2 = 123

[table-2]
key1 = "another string"
key2 = 456
"""

data = toml.loads(config)
print(data)
"""
{'other-table-1': {'key1': 'some string', 'key2': 123},
 'other-table-2': {'key1': 'another string', 'key2': 456},
 'table-1': {'key1': 'some string', 'key2': 123},
 'table-2': {'key1': 'another string', 'key2': 456}}
"""

不过注意:我们必须要把 other-table-1 和 other-table-2 定义在上面,如果我们定义在下面看看会有什么后果:

import toml

config = """
[table-1]
key1 = "some string"
key2 = 123

[table-2]
key1 = "another string"
key2 = 456

other-table-1.key1 = "some string"
other-table-1.key2 = 123

other-table-2.key1 = "another string"
other-table-2.key2 = 456
"""

data = toml.loads(config)
print(data)
"""
{
    'table-1': {'key1': 'some string', 'key2': 123},
    'table-2': {'key1': 'another string',
                'key2': 456,
                'other-table-1': {'key1': 'some string', 
                                  'key2': 123},
                'other-table-2': {'key1': 'another string', 
                                  'key2': 456}}
}
"""

你可能已经猜到了,它们被视为了“table-2”对应的字典键。此外我们还可以将上面两种方式结合起来:

import toml

config = """
# [] 里面的不再是一个普通的键,而是点分隔键
# 另外键名周围的空格会被忽略,但是最好不要有
[dog  .  "tater.man"]  
type.name = "哈巴狗"
"""

data = toml.loads(config)
print(data)
"""
{
    'dog': {'tater.man': {'type': {'name': '哈巴狗'}}}
}
"""

表的里面也是可以没有键值对的:

import toml

config = """
[x.y.z.w.a.n]

[x.m]

[x.n]

[x]
a.b.c = "xxx"
"""

data = toml.loads(config)
print(data)
"""
{'x':
    {
        'a': {'b': {'c': 'xxx'}},
        'm': {},
        'n': {},
        'y': {'z': {'w': {'a': {'n': {}}}}}
    }
}
"""

总的来说还是蛮强大的,但是要注意:不能重复定义。

行内表

行内表提供了一种更为紧凑的语法来表示表,因为上面每一个键值对都需要单独写一行,比如:

[table1]
a = 1
b = 2
c = 3
# 最终可以得到 
# {'table1': {'a': 1, 'b': 2, 'c': 3}}

但是除了上面的表达方式之外,我们还可以采用行内表:

import toml

config = """
# 和 Python 字典的表示方式略有不同
# 并且也支持多种 key
table1 = {a = 1, b = "二", c.a = "3"}
table2 = {c."b c".d = "4"}
"""

data = toml.loads(config)
print(data)
"""
{
    'table1': {'a': 1, 'b': '二', 'c': {'a': '3'}},
    'table2': {'c': {'b c': {'d': '4'}}}
}
"""

表数组

然后来看看数组和表的结合:

import toml

config = """
[name1]
girl = "古明地觉"

[[name2]]
girl = "古明地恋"

[name3]
[[name4]]
"""

data = toml.loads(config)
print(data)
"""
{'name1': {'girl': '古明地觉'},
 'name2': [{'girl': '古明地恋'}],
 'name3': {},
 'name4': [{}]}
"""

当使用 [[]] 的时候,相当于在 [] 的基础上套上一层列表。任何对表数组的引用都会指向该数组中最近定义的表元素,这使得我们能够在最近的表内定义子表甚至子表数组。

我们再举个更复杂的例子:

import toml

config = """
[[fruits]]  
name = "苹果"  

# 会操作 [] 里面最近定义的 {}
[fruits.physical]  
color = "红色"
shape = "圆形"

[[fruits.varieties]]  # 嵌套表数组
name = "蛇果"    

[[fruits.varieties]]
name = "澳洲青苹" 

[[fruits]]
name = "香蕉" 

[[fruits.varieties]]
name = "车前草"  
"""

data = toml.loads(config)
print(data)
"""
{
    'fruits':
        [
            {
                'name': '苹果',
                'physical': {'color': '红色', 
                             'shape': '圆形'},
                'varieties': [{'name': '蛇果'}, 
                              {'name': '澳洲青苹'}]
            },
            {
                'name': '香蕉', 
                'varieties': [{'name': '车前草'}]
            }
        ]
}
"""

很明显这种定义不是很常用,配置文件应该要非常直观才对,但这已经不是很好理解了。

以上がPython を使用して toml 構成ファイルを解析する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。