当前位置:

首页 > 编程开发 > 怎么用Python解析toml配置文件

怎么用Python解析toml配置文件

举个例子有了ini和yaml,相信toml学习来也很简单,先直接看一个例子吧。importtomlconfig="""title="toml小栗子"[owner]name="古明地觉"age=17place="东方地灵殿"nickname=["小五","少女觉","觉大人"][database]host="127.0.0.1"port=5432username="satori"password="123456"echo=true[server][server.v1]api="1.1"enable=fals

本文目录

    举个例子

    有了 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 里面的 section,每个 section 都是字典中的一个 key,然后该 key 也对应一个字典。但是我们注意看最开始的 title,由于它上面没有 section,所以它是一个单独的 key。

    而且还有一点就是 toml 支持嵌套,我们看到 server.v1,表示 v1 是 server 对应的字典里面的一个 key,然后 v1 对应的值还是一个字典。

    toml 变得更加简单了,而且写来也非常像 Python,它有如下特点:

    toml 文件是大小写敏感的;

    toml 文件必须是有效的 UTF-8 编码的 Unicode 文档;

    toml 文件的空白符应该是 Tab 或者空格;

    toml 文件的换行是 LF 或者 CRLF;

    然后我们来介绍一下 toml 的数据结构。

    注释

    toml 采用 # 表示注释,举个例子:

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

    可以解析一下看看会得到什么,剧透:会得到只包含一个键值对的字典。

    键值对

    TOML 文档最基本的构成区块是键值对,键名在等号的左边、值在右边,并且键名和键值周围的空白会被忽略。此外键、等号和值必须在同一行(不过有些值可以跨多行)。

    key = "value"

    键名可以是裸露的(裸键),引号引起来的(引号键),或点分隔的(点分隔键)。裸键只能包含:ascii 字符、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'}
    """

    如果键是浮点数,那么需要使用引号括起来,否则会被解释为点分隔键。

    看完了键,再来看看值(value),其实对于 toml 来说,值比键要简单的多得多。

    字符串

    字符串共有四种方式来表示:基础式的,多行基础式的,字面量式的,和多行字面量式的。

    1)基础字符串由引号包裹,任何 Unicode 字符都可以使用,除了那些必须转义的。

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

    2)多行字符串由三个引号包裹,允许换行,注意:紧随开头引号的换行会被去除,其它空白和换行会被原样保留。

    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 也是有效的,并等同于无前缀的零。非负整数值也可以用十六进制、八进制或二进制来表示。

    # 带有 `0x` 前缀的十六进制,大小写均可
    hex1 = 0xDEADBEEF
    hex2 = 0xdeadbeef
    hex3 = 0xdead_beef
    
    # 带有 `0o` 前缀的八进制
    oct1 = 0o01234567
    oct2 = 0o755 # 对于表示 Unix 文件权限很有用
    
    # 带有 `0b` 前缀的二进制
    bin1 = 0b11010110

    浮点数

    一个浮点数由一个整数部分(遵从与十进制整数值相同的规则)后跟上一个小数部分、或一个指数部分组成。如果小数部分和指数部分兼有,那小数部分必须在指数部分前面。

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

    小数部分是一个小数点后跟一个或多个数字,一个指数部分是一个 E(大小写均可)后跟一个整数部分(遵从与十进制整数值相同的规则,但可以包含前导零)。小数点,如果有用到的话,每侧必须紧邻至少一个数字。

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

    与整数相似,可以使用下划线来增强可读性,每个下划线必须被至少一个数字围绕。

    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

    日期

    可以是普通的 datetime,或者是遵循 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)}
    """

    数组

    语法和 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]}
    """

    表

    表,完全可以把它想象成 ini 的 section。

    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' 对应的字典里面的 key 了。此外我们还可以将上面两种方式结合起来:

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

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

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 Python
    相关文章 更多
    python删除一个列表里的重复元素的方法与代码示例
    python删除一个列表里的重复元素的方法与代码示例

    学习如何使用Python高效删除列表中的重复元素。本文提供5种常见方法的代码示例,涵盖保持顺序与不保持顺序的场景,适合初学者和进阶开发者参考。

    Python写接口的步骤及完整代码示例
    Python写接口的步骤及完整代码示例

    详细讲解使用Python编写Web接口的核心步骤与完整代码示例,涵盖环境准备、路由定义、数据校验、服务启动及调试测试方法。

    codex怎么读取word文档及docx文件操作教程
    codex怎么读取word文档及docx文件操作教程

    介绍如何利用编程工具读取和解析Word文档(docx格式),涵盖基础文本提取代码示例、结构化数据处理逻辑,以及处理复杂排版时的技术局限与替代方案。

    怎么在Python中调用C语言代码提升性能
    怎么在Python中调用C语言代码提升性能

    详细讲解在Python中调用C语言代码提升性能的完整实践指南,包含原理分析、编译步骤、ctypes与CFFI具体实现、性能对比及常见陷阱。

    Python与C语言的性能差异及底层原理
    Python与C语言的性能差异及底层原理

    深入解析Python与C语言在执行效率上的数量级差异,从编译机制、变量内存布局、动态类型推断到GIL锁,系统阐明底层核心原理。

    Python和C语言哪个更适合编程入门
    Python和C语言哪个更适合编程入门

    客观对比Python与C语言在心智负担、底层机制与学习反馈上的核心差异,提供清晰有据的选择标准与切实的入门学习路径。

    selenium上传文件教程本地文件路径设置方法
    selenium上传文件教程本地文件路径设置方法

    深入解析Selenium处理文件上传的技术细节,涵盖标准HTML控件的路径直接注入法与非标准控件的系统级模拟方案,提供Windows与Linux环境下的路径设置最佳实践及常见异常排查。

    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景
    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景

    针对大数据工程场景,系统对比Java、Scala与Python在执行性能、生态结合、开发效率和维护成本上的核心差异,给出清晰的架构选型依据与落地方案。

    langgraph python guide中文入门教程详解
    langgraph python guide中文入门教程详解

    本篇LangGraph Python中文入门教程详解,系统梳理StateGraph状态机定义、节点编写、边与条件路由、检查点持久化(MemorySaver)等核心机制,提供从环境安装到完整循环智能体构建的代码示例与实操指导。

    Windows 安装 Python:从官方入口到虚拟环境的可复现实践
    Windows 安装 Python:从官方入口到虚拟环境的可复现实践

    面向后端开发者,基于 Python 官方文档说明如何在 Windows 上安装 Python、创建 venv 虚拟环境及使用 pip 管理依赖。包含可复制命令、验证方法及工具选择边界,避免常见配置误区。

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。