如何通过python正确读写.cfg文件

问题描述 投票:0回答:2

我需要在 Python 中读取和写入

.cfg
文件方面的帮助。我想要读写的
.cfg
文件具有特定的格式,无法更改。

示例

.cfg
文件:

[META]
title = "Xxxx xxxx"
creator = "xxx"
artist = "xxxx"
artist = "xxx xxx"
title = "xxx xxx (xxxxxx)"
length = "4:59"

一些

.cfg
文件也可以具有非常长的格式(我觉得很奇怪)。这只是一个很长的
.cfg
文件的片段:

[EASY]
bpm = 100
offset = 0
spawn = [63, 111, 161, 201, 285, 339, 342, 347, 380, 388, 422, 449, 470, 507, 511, 531, 551, 555, 583, 591, 634, 638, 642, 701, 783]
half_spawn = [0, 1, 8, 16]
initial_data = {
    "type": 1,
    "animation": "xxxx.png",
    "looping": false,
    "fx": "",
    "background": [
        "xxxx.png",
        {
            "static": false
        }
    ],
    "voice_bank": {

    }
}

我使用过像 libconfconfigparser 这样的库,但这些库都不理解文件格式,并且报告了多个错误。

我在尝试读取此类文件时最幸运的是使用这样的东西:

lines = open('./test.cfg').read().splitlines()

但即使这样也会导致多种格式问题,并且很难处理。我看过其他关于此的帖子,但它们没有完全相同的格式。

我对 Python 的经验不是很丰富,非常感谢任何帮助。

python config configuration-files
2个回答
1
投票

您可以编写一个小型状态机来支持“复杂”的多行值,以及标准库的

ast.literal_eval()
json.loads()
将值转换为 Python 数据。

这对于诸如

Vector3(0, 0, 0)
之类的调用会失败,这些调用在 Godot 文件中有效,但是您可以很容易地将代码添加到例如跳过这些,或使用例如
pure-eval
库来处理它们。

假设

data_fp
变量是一个打开的文件(我使用
io.StringIO()
进行测试),

import ast
import io
import json
import sys

def parse_godot_value(value: str):
    # The Godot complex value seems to be pretty much just JSON.
    return json.loads(value)


def parse_godotesque_ini(fp):
    current_section = None
    complex_key = None
    complex_value = None
    for line in fp:
        line = line.rstrip()
        if not line:
            continue
        if line.startswith("["):
            current_section = line.strip("[]")
            continue
        if complex_value is None:  # Not busy parsing a complex value
            key, _, value = line.partition("=")
            key = key.strip()
            value = value.strip()
            if not (key and value):
                continue
            if value == "{":
                complex_key = key
                complex_value = ["{"]  # Start of a complex value
            else:
                yield (current_section, key, parse_godot_value(value))
        else:  # Busy parsing a complex value
            complex_value.append(line)
            if line == "}":  # End of a complex value
                yield (current_section, complex_key, parse_godot_value("\n".join(complex_value)))
                complex_key = None
                complex_value = None


for section, key, value in parse_godotesque_ini(data_fp):
    print(section, key, value)

打印出来

META title Xxxx xxxx
META creator xxx
META artist xxxx
META artist xxx xxx
META title xxx xxx (xxxxxx)
META length 4:59
EASY bpm 100
EASY offset 0
EASY spawn [63, 111, 161, 201, 285, 339, 342, 347, 380, 388, 422, 449, 470, 507, 511, 531, 551, 555, 583, 591, 634, 638, 642, 701, 783]
EASY half_spawn [0, 1, 8, 16]
EASY initial_data {'type': 1, 'animation': 'xxxx.png', 'looping': False, 'fx': '', 'background': ['xxxx.png', {'static': False}], 'voice_bank': {}}

对于您粘贴的数据。

祝你好运!


编辑:

为了发出类似的格式,

def write_godotesque_ini(fp, data_dict):
    for section, items in data_dict.items():
        fp.write(f"[{section}]\n")
        for key, value in items.items():
            indent = 4 if isinstance(value, dict) else None
            fp.write(f"{key} = {json.dumps(value, indent=indent)}\n")
        fp.write("\n")


new_data = {
    "META": {
        "title": "Xxxx xxxx",
        "creator": "xxx",
    },
    "EASY": {
        "half_spawn": [0, 1, 8, 16],
        "initial_data": {
            "type": 1,
            "animation": "xxxx.png",
        },
    },
}

write_godotesque_ini(sys.stdout, new_data)

[META]
title = "Xxxx xxxx"
creator = "xxx"

[EASY]
half_spawn = [0, 1, 8, 16]
initial_data = {
    "type": 1,
    "animation": "xxxx.png"
}

到标准输出。


-1
投票

一种可能的解决方案是使用 python-libconf 库,它是一个纯 Python

这是一个使用示例:

import libconf
with io.open('file.cfg', encoding='utf-8') as f:
    cfg = libconf.load(f)
© www.soinside.com 2019 - 2024. All rights reserved.