我需要在 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": {
}
}
我使用过像 libconf 和 configparser 这样的库,但这些库都不理解文件格式,并且报告了多个错误。
我在尝试读取此类文件时最幸运的是使用这样的东西:
lines = open('./test.cfg').read().splitlines()
但即使这样也会导致多种格式问题,并且很难处理。我看过其他关于此的帖子,但它们没有完全相同的格式。
我对 Python 的经验不是很丰富,非常感谢任何帮助。
您可以编写一个小型状态机来支持“复杂”的多行值,以及标准库的
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"
}
到标准输出。
一种可能的解决方案是使用 python-libconf 库,它是一个纯 Python
这是一个使用示例:
import libconf
with io.open('file.cfg', encoding='utf-8') as f:
cfg = libconf.load(f)