Heim  >  Artikel  >  Backend-Entwicklung  >  So verwenden Sie Python zum Parsen von ToML-Konfigurationsdateien

So verwenden Sie Python zum Parsen von ToML-Konfigurationsdateien

王林
王林nach vorne
2023-05-21 11:20:041173Durchsuche

Zum Beispiel

Mit ini und yaml ist toml meiner Meinung nach auch sehr einfach zu lernen. Schauen wir uns ein Beispiel direkt an.

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 ist in der Form var = value konfiguriert, und es gibt auch Abschnitte ähnlich wie ini. Jeder Abschnitt ist ein Schlüssel im Wörterbuch, und der Schlüssel entspricht auch einem Wörterbuch. Aufgrund des fehlenden Abschnitts müssen wir den Anfangstitel notieren, es handelt sich also um einen separaten Schlüssel.

Ein weiterer Punkt ist, dass toml die Verschachtelung unterstützt. Wir sehen server.v1, was bedeutet, dass v1 ein Schlüssel im Wörterbuch ist, der dem Server entspricht, und der Wert, der v1 entspricht, immer noch ein Wörterbuch ist.

toml ist einfacher geworden und ist sehr ähnlich wie Python geschrieben. Es verfügt über die folgenden Funktionen:

toml-Dateien unterscheiden zwischen Groß- und Kleinschreibung; #toml-Datei muss ein gültiges UTF-8-codiertes Unicode-Dokument sein;

Das Leerzeichen der toml-Datei sollte Tabulator oder Leerzeichen sein;

Der Zeilenumbruch der toml-Datei sollte LF oder CRLF sein;# 🎜🎜#

Dann stellen wir die Datenstruktur von toml vor.

Hinweis

toml verwendet #, um Kommentare darzustellen, zum Beispiel:

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

Sie können es analysieren und sehen, was Sie bekommen, Spoiler: Sie wird erhalten Ein Wörterbuch, das nur ein Schlüssel-Wert-Paar enthält.

Schlüssel-Wert-Paar

Der Basisblock ist ein Schlüssel-Wert-Paar, mit dem Schlüsselnamen auf der linken Seite des Gleichheitszeichens und dem Wert auf der rechten Seite. Dabei werden der Schlüsselname und die Schlüsselwertumgebung ignoriert. Ein leeres TOML-Dokument. Darüber hinaus müssen sich Schlüssel, Gleichheitszeichen und Wert in derselben Zeile befinden (obwohl einige Werte mehrere Zeilen umfassen können).

key = "value"

Schlüsselnamen können in Form von einfachen Schlüsseln, Anführungszeichen oder durch Punkte getrennten Schlüsseln angezeigt werden. Nackte Schlüssel dürfen nur ASCII-Zeichen, Zahlen, Unterstriche und Bindestriche enthalten.

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'}
"""

Wenn es sich nicht um einen bloßen Schlüssel handelt, muss er in Anführungszeichen gesetzt werden. Zu diesem Zeitpunkt unterstützen wir jedoch auch die Verwendung eines größeren Bereichs von Schlüsselnamen, jedoch mit Ausnahme spezieller Szenarien Schlüssel ist die beste Vorgehensweise.

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'}
"""

Hinweis: Bloße Schlüssel dürfen nicht leer sein, aber leere Anführungszeichen sind zulässig (obwohl nicht empfohlen).

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

Dann gibt es durch Punkte getrennte Schlüssel, bei denen es sich um eine Reihe von bloßen oder in Anführungszeichen gesetzten Schlüsseln handelt, die durch Punkte verbunden sind, wodurch wir ähnliche Eigenschaften zusammenfassen können:

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}}}
}
"""

Mal sehen Das Punkttrennzeichen ist an dieser Stelle gut, die verschachtelte Struktur wird automatisch implementiert und der Leerraum um das Punkttrennzeichen wird ignoriert.

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

Hinweis: Es ist nicht möglich, denselben Schlüssel mehrmals zu definieren.

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)
"""

Das Gleiche gilt für durch Punkte getrennte Schlüssel. Solange ein Schlüssel nicht direkt definiert wurde, können wir ihm und seinen untergeordneten Schlüsselnamen immer noch Werte zuweisen.

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}
}
"""

Aber die folgende Operation ist nicht möglich:

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

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

Wie Sie sehen können, ähnelt es wirklich Python. Dann sprechen wir über einen Sonderfall:

import toml

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

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

Wenn der Schlüssel eine Gleitkommazahl ist, muss er in Anführungszeichen gesetzt werden, andernfalls wird er als durch Punkte getrennter Schlüssel interpretiert.

Nachdem wir die Schlüssel gelesen haben, schauen wir uns die Werte an. Tatsächlich sind die Werte für toml viel einfacher als die Schlüssel.

String

Es gibt vier Möglichkeiten, Zeichenfolgen darzustellen: einfach, mehrzeilig, einfach, literal und mehrzeilig.

1) Die Basiszeichenfolge ist in Anführungszeichen gesetzt und es kann jedes Unicode-Zeichen verwendet werden, mit Ausnahme derjenigen, die maskiert werden müssen.

import toml

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

data = toml.loads(config)
print(data)
"""
{'str': '我是一个字符串,"你可以把我引起来"'}
"""
Mehrzeilige Zeichenfolgen können in drei Anführungszeichen gesetzt werden und können Zeilenumbrüche enthalten. Es ist jedoch zu beachten, dass der erste Zeilenumbruch nach dem öffnenden Anführungszeichen entfernt wird und andere Leerzeichen und Zeilenumbrüche beibehalten werden.

import toml

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

data = toml.loads(config)
print(data)
"""
{'str': '玫瑰是红色的\n紫罗兰是蓝色的\n'}
"""
Die Anführungszeichen hier können doppelte oder einfache Anführungszeichen sein.

Ganzzahl

Ganzzahlen sind reine Zahlen, denen ein Pluszeichen vorangestellt werden kann, und negativen Zahlen kann ein Minuszeichen vorangestellt werden.

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}
"""

Aber Achtung: Zahlen können nicht mit Null beginnen, außer 0 selbst. Null, -0 und +0 ohne Präfix sind gleichwertig. Nichtnegative Ganzzahlwerte können auch hexadezimal, oktal oder binär dargestellt werden.

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

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

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

Gleitkommazahl

Eine Gleitkommazahl kann aus einem ganzzahligen Teil und einem Dezimalteil oder auch aus einem Exponententeil bestehen. Für die Ganzzahl- und Bruchteile gelten dieselben Regeln wie für dezimale Ganzzahlwerte. Wenn es sowohl einen Dezimalteil als auch einen Exponententeil gibt, muss der Dezimalteil vor dem Exponententeil stehen.

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}
"""

Der Dezimalteil ist ein Dezimalpunkt, gefolgt von einer oder mehreren Ziffern, ein Exponententeil ist ein E (entweder Groß- oder Kleinschreibung), gefolgt von einem ganzzahligen Teil (folgt den gleichen Regeln wie dezimale ganzzahlige Werte). , kann aber führende Nullen enthalten). Der Dezimalpunkt muss, sofern er verwendet wird, auf jeder Seite unmittelbar neben mindestens einer Ziffer stehen.

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

Ähnlich wie ganze Zahlen können Unterstriche zur Verbesserung der Lesbarkeit verwendet werden, und jeder Unterstrich muss von mindestens einer Ziffer umgeben sein.

flt8 = 224_617.445_991_228

Gleitkommawerte -0,0 und +0,0 sind gültig und sollten IEEE 754 entsprechen. Es können auch spezielle Gleitkommawerte dargestellt werden:

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

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

Boolescher Wert

Boolesche Werte sind einfach so, aber in Kleinbuchstaben.

bool1 = true
bool2 = false

Date

kann ein gewöhnliches Datum/Uhrzeit oder ein Datum im ISO-8859-1-Format sein.

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

Die Syntax ähnelt der Python-Liste:

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]}
"""

Das Array kann sich über Zeilen erstrecken, und nach dem kann ein Endkomma stehen letzter Wert des Arrays (auch abschließendes Komma genannt).

import toml

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

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

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

Table

Table, Sie können es sich als einen Abschnitt von ini vorstellen.

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}}
"""

Aber wir haben eine ähnliche Struktur schon einmal implementiert, ja, es ist das Punkttrennzeichen:

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': '车前草'}]
            }
        ]
}
"""

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

Das obige ist der detaillierte Inhalt vonSo verwenden Sie Python zum Parsen von ToML-Konfigurationsdateien. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen