什么是一种好的 Python 配置文件格式,可以轻松地由一个脚本编辑并由另一个脚本轻松安全地读取?

What is a good Python configuration file format that can be edited by one script easily and read by another script easily and safely?

假设我有两个 Python 脚本。一个脚本是一个 Web 界面,可以让人们编辑配置文件。另一个脚本是根据该文件中定义的配置在后台执行各种操作的脚本,它会在循环中每隔几秒重新加载一次。

这样的配置文件用什么格式比较好?我希望格式是人类可读和可编辑的,同时也易于写入和读取而不会发生冲突。

目前,我认为 json 模块可能是一个不错的选择,其中配置本质上是一个以明文形式保存到文件中的字典,并从该明文文件读取到字典中。这是一种安全的方法吗?有更好的方法吗?如果一个脚本试图从文件中读取而另一个脚本正在写入文件,是否会出现问题?应该如何解决?

所以,作为一个简单的例子,这里有两个脚本。一种是将配置写入 JSON 纯文本文件,另一种是从文件中读取配置:

作家

import random

import json

while True:
    config = {"a": 1, "b": random.randint(1, 2)}
    with open("config.json", "w") as file_config:
        json.dump(config, file_config)

reader

import json

while True:
    with open("config.json") as file_JSON:
        config = json.load(file_JSON)
    print(config)

当这两个脚本同时为 运行 时,reader 脚本会很快产生以下错误:

Traceback (most recent call last):
  File "2_script.py", line 5, in <module>
    config = json.load(file_JSON)
  File "/usr/lib/python3.5/json/__init__.py", line 268, in load
    parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, **kw)
  File "/usr/lib/python3.5/json/__init__.py", line 319, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.5/json/decoder.py", line 339, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.5/json/decoder.py", line 357, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

应该如何解决?

听起来您正在寻找两个功能:

  1. human-readable配置文件
  2. 支持一个进程写入文件而其他进程正在读取文件

我不知道这两个功能的简单解决方案,但我可以提出一些建议。

  1. 对适用于您的平台的文件锁定进行一些研究。这可能是获得您想要的东西的最佳选择。
  2. 考虑使用 SQLite 数据库而不是 human-readable 配置文件。 SQLite supports 多个读取器和一个写入器进程。您可以编写一个命令行工具来转储配置供用户查看。
  3. 尝试 "good enough" 尝试读取文件的解决方案,并处理读取不完整文件的任何问题。需要考虑的一些技巧是添加 "end of file" 标记或校验和以确保您没有读取不完整的文件,以及以临时名称写入文件,然后将其重命名为活动名称。失败后休眠重试。
  4. 在进程之间进行通信以在可以安全读取文件时通知它们,或者直接将配置数据发送到每个进程。如果 Web 服务启动后台进程,它们可以使用队列或进程池。或者,他们可以通过命名管道进行通信。

关于格式,我会考虑三种选择:

  1. INI 格式 - 过时的格式,但它受 built-in configparser 模块支持
  2. YAML 格式 - 我更喜欢这种格式而不是 JSON,因为它支持评论
  3. JSON 格式 - 流行,但不支持注释:您要么必须使用像 "comment" 这样的特殊属性名称,要么在解析文件之前删除注释