探索 Python 配置文件的最佳实践
首先看几种常见的存储配置文件的方式:
# 专用的 py 文件存储
Python 不是配置格式。 最佳做法不是将这些内容存储在.py 文件中,而是将其存储为 YAML 或 JSON 或 INI 或任何其他格式并加载到其中。如果您需要在程序运行时更改配置,则可以 让线程监视文件描述符中的更改并适当地重新加载配置。
如果您将配置存储在.py 文件中以进行长时间运行(例如,例如 Web 服务器),则基本上需要重新启动整个程序(python 的重装是要使用的屁股上的真正痛苦,并且很多 非常健壮的 Web 框架在 IMO 方面仍然存在很多麻烦。 将其保存在配置文件中还意味着最终用户可以随意更改配置(而代码可能已经预先编译为.pyc 文件中的字节码)。
话虽这么说,如果它是最适合您的变量,并且变量在程序的整个生命周期内都不会改变,则将它们存储在.py 文件中并不是什么大问题。 随着程序的发展,您将不得不重新考虑该问题。我目前正在开发一个程序,该程序将其配置存储在 python 文件中,并且要更改任何内容都非常麻烦。
# JSON
# 不使用 json 的理由
尽管作为基于字符串的人类可读的数据交换格式非常好,但是:
- 没有注释
- 逗号太烦人 参见:
Why JSON isn't a Good Configuration Language - Lucidchart (opens new window)
上文翻译:为什么说 JSON 不适合做配置文件? - 简书 (opens new window)
# YAML
YAML 格式被设计为 JSON 的超集,同时更易于手工操作。 YAML 有三个主要问题。
- 规范太多:如果打印在 letter 尺寸的纸上,则会有 86 页。这就使得有人可能会使用 YAML 的功能与一个解析器一起工作,而不是另一个解析器。有人建议在一个子集上进行标准化,但这基本上意味着要创建一个特定于该文件的新标准,这个标准是不容易长期处理的。
- YAML 默认本身并不安全。该规范允许在处理配置数据时最好避免代码的任意执行。当然可以避免这种行为 - 例如,PyYAML 提供了一个 safe_load 操作 - 但是如果任何工具不小心使用 load,那么它们会自行开启任意代码执行。虽然这个 PEP 专注于构建固有涉及代码执行的项目,但其他配置数据(如项目名称和版本号)最终可能会在相同的文件中随意执行任意代码。
- 最后,最流行的 YAML 的 Python 实现是 PyYAML,它是一个包含几千行代码的大型项目,也是一个可选的 C 扩展模块。虽然本身并不一定是个问题,但对于像 pip 这样的项目来说,这更像是一个问题,因为他们很可能需要将 PyYAML 作为依赖项供应商,以便完全独立(否则,最终会导致您安装需要安装工具的工具才能正常工作)。 PyYAML 的一个概念验证重新工作已经完成,看看有多容易的可能供应一个简单版本的库,这表明它是一种可能性。
# Configparser
一个基于 configparser INI 风格配置文件。 不幸的是,没有关于什么 configparser 接受的规范,导致版本之间的支持倾斜。 例如,Python 2.7 中的 ConfigParser 接受的内容与 Python 3 中的 configparser 接受的内容不同。 虽然可以标准化 Python 3 接受的内容,并简单地供应 configparser 模块的 backport,但这确实意味着此 PEP 必须编码,所有项目希望使用 configparser 的 backport 才能使用此 PEP 指定的元数据。 这是过度限制性的,如果有人不知道预期特定版本的 configparser 会导致混淆。
# 可选
- YAML,JSON,ini,XML 用来做配置文件,优缺点分别是什么? - 知乎 (opens new window)
- HOCON (opens new window)
- chimpler/pyhocon: HOCON parser for Python (opens new window)
# 总结
# 横向对比
Feature | TOML | YAML | JSON | CFG/INI |
---|---|---|---|---|
Well-defined | yes | yes | yes | |
Real data types | yes | yes | yes | |
Reliable Unicode | yes | yes | yes | |
Reliable comments | yes | yes | ||
Easy for humans to edit | yes | ?? | ?? | |
Easy for tools to edit | yes | ?? | yes | ?? |
In standard library | yes | yes | ||
Easy for pip to vendor | yes | n/a | n/a |
表中的“??”表示大多数人倾向于回答“是”的项目,但实际上由于缺乏明确的规范或由于底层文件格式规范会异常复杂导致答案为否)
pytoml TOML 解析器是约 300 行的纯 Python 代码,因此不在标准库之内就算不上什么特别严重的瑕疵。
Python 文件也被讨论为一种潜在的格式,但是在文件格式审查中并未考虑(因为它们不是常见的预先存在的文件格式)。