Python 配置文件:有啥文件格式推荐吗? INI格式还合适吗?看起来很老派
Posted
技术标签:
【中文标题】Python 配置文件:有啥文件格式推荐吗? INI格式还合适吗?看起来很老派【英文标题】:Python configuration file: Any file format recommendation? INI format still appropriate? Seems quite old schoolPython 配置文件:有什么文件格式推荐吗? INI格式还合适吗?看起来很老派 【发布时间】:2012-01-03 18:52:53 【问题描述】:我需要为 Python 应用程序存储配置(键/值),我正在寻找将这些配置存储在文件中的最佳方式。
我遇到了 Python 的ConfigParser,我想知道 INI 文件格式现在是否真的仍然合适?! 是否存在更新的格式或者 INI 仍然是推荐的方式? (XML、JSON、...)
请分享您的意见/建议...
【问题讨论】:
如果你只是存储一个键值对列表,我认为 INI 没问题! 还有带搁置的dict对象类型。不过可能已经过头了。 @Matt:我认为它很容易使用,可能比使用ConfigParser
更容易
@Matt:你能在答案中列出你的意思吗?
只是重申其他人所说的:还有其他选择,但 INI 样式配置可能至少与其中任何一个一样好。它是可读的,它不需要任何更多的依赖,你的代码可以修改它......不要因为它太旧而忽略它。
【参考方案1】:
考虑使用纯 Python 文件作为配置文件。
一个例子(config.py
):
# use normal python comments
value1 = 32
value2 = "A string value"
value3 = ["lists", "are", "handy"]
value4 = "and": "so", "are": "dictionaries"
在您的程序中,使用exec
(docs) 加载配置文件:
from pathlib import Path
if __name__ == "__main__":
config =
exec(Path("config.py").read_text(encoding="utf8"), , config)
print(config["value1"])
print(config["value4"])
我喜欢这种方法,原因如下:
在简单的情况下,该格式与创建 INI 样式的配置文件一样容易。它还与 INI 文件共享一个重要特征:它非常适合版本控制(这对于 XML 不太适用,也许对于 JSON 也是如此) 我喜欢使用实际编程语言编写配置文件所带来的灵活性。该方法被广泛使用,举几个例子:
Django 站点的设置位于settings.py 中。 Django 不使用execfile
,它使用import
读取/执行settings.py
AFAIK,但最终结果是一样的:设置文件中的代码被执行。
bash shell 在启动时读取并执行~/.bashrc
。
Python 解释器在启动时导入 site.py
。
【讨论】:
如果程序以root权限运行,配置文件应该有root权限。 我不太喜欢这个。 distutils 中的setup.py
已更改为声明性格式,以防止其变得混乱复杂。这会带来滥用的可能性(if 语句等)。但是,如果您要使用 ast
模块解析文件,然后只允许简单的分配,它可能会起作用。
如果您以后希望能够从 GUI 更改设置,或者以任何方式以编程方式设置它们,这也会变得很棘手。修改声明性上下文文件比修改脚本要简单得多。
Kugel:管理起来很痛苦。它甚至不读取/执行文件。它导入它,这使得必须手动配置 sys.path 和所有其他类型的麻烦。从操作的角度来看,这是一场真正的噩梦。这可能是我最不喜欢 Django 的一点。
我越是考虑这个解决方案,我就越喜欢它【参考方案2】:
INI 完全没问题,正如其他人所说,您的配置文件的格式实际上取决于您将如何使用它。
我个人是YAML 的粉丝:简洁、易读、灵活。
Google 似乎分享了我的热情,因为他们也在 Google App Engine 中使用它。 python解析器是here。
【讨论】:
YAML 的缺点是你需要一个额外的依赖来解析它。【参考方案3】:Dictionaries 也很受欢迎。基本上是一个哈希表。
"one": 1, "two": 2
是一个例子,有点像 json。
然后你可以像mydict["one"]
一样调用它,它会返回1。
然后你可以使用shelve将字典保存到文件中:
mydict = shelve.open(filename)
# then you can call it from there, like
mydict["one"]
所以,它比 ini 文件要容易一些。你可以很容易地添加列表或更改选项等内容,然后一旦关闭它,它就会将其写回。
这是我的意思的一个简单例子:
import shelve
def main():
mydict = shelve.open("testfile")
mydict["newKey"] = value("some comment", 5)
print(mydict["newKey"].value)
print(mydict["newKey"].comment)
mydict.close()
class value():
def __init__(self, comment, value):
self.comment = comment
self.value = value
if __name__ == '__main__':
main()
【讨论】:
我猜对 json 的评论在这里也是有效的:No cmets possible?! @gecoo 不完全是。您可以将对象存储到字典中。因此,您始终可以将值存储为对象并在其中添加注释。所以它不完全像json。 @geeco 我用一些简单的示例代码更新了我的答案。这不会是纯文本的,因此如果您想查看它,将不容易阅读。真的只是取决于你在寻找什么。 我不喜欢二进制格式的配置设置。有两个原因:1. 您需要自定义程序来查看和编辑设置(相对于基于文本格式的文本编辑器) 2. 二进制配置文件无法轻松进行版本控制或与其他配置文件进行比较。 “注册表”?呸!拿大蒜和圣水!【参考方案4】:这完全取决于您的要求。如果(如您所说)您只需要键/值对,那么 ini 文件(或其他“普通”配置文件)将非常适合您。不,它们并没有过时,因为它们仍在使用中。
如果您有分层结构并且还想使用更复杂的方法(例如:XML 文件验证、命名空间等),XML/JSON 是完美的。
【讨论】:
我建议不要使用 JSON,因为(至少使用 Python 的 json 解析器)你不能在 JSON 中包含 cmets。【参考方案5】:查看ConfigObj,它是迄今为止我发现的最巧妙的方法,而且绝对比 ConfigParser 更灵活。就我个人而言,我不是基于 YAML 的粉丝,因为它的“灵活性”使其难以与 Augeas 等工具一起使用。
【讨论】:
自从我回答这个问题后,我的一位同事发布了一个很好的关于 configparser、argparse 和 ENV 变量的包装器,名为crumbs。因为真的,您的配置不应该来自这三个地方中的任何一个,而无需您自己将不同的库连接在一起吗?【参考方案6】:这取决于配置文件的使用方式。
INI 文件的优点之一是它们非常易于阅读和理解。如果您手动编辑配置,在 JSON 或 XML 文件中出错会容易得多。 php 仍然使用 INI 文件。
但是,如果您的配置不适合手动编辑,请使用您喜欢的任何格式,因为 INI 不是最容易解析的。
【讨论】:
【参考方案7】:为了完整起见,您还可以在“shlex”模块的帮助下使用 shell 样式的配置格式。如果您有一组固定的配置参数,则可以将其与“optparse”模块结合使用。
from optparse import OptionParser
_o = OptionParser("%prog [options] configfiles...")
_o.add_option("--hostname", metavar="HOSTNAME", default="10.0.0.1")
_o.add_option("--username", metavar="USERNAME", default="admin")
_o.add_option("--password", metavar="PASSWORD", default="admin")
import shlex
def parse(filename, defaults):
opt, args = _o.parse_args(shlex.split(open(filename).read()), defaults)
return opt
if __name__ == "__main__":
import sys
values, args = _o.parse_args()
for arg in args:
values = parse(arg, values)
values, args = _o.parse_args(values = values)
for name in _o.defaults:
print name, "=", getattr(values, name)
该示例显示了如何链接 ini 文件以获得一组默认值和用户定义的重新定义。所以假设你有两个文件包含
file1.ini:
--hostname 10.2.3.4
--password admin-sc
file2.ini:
--username "foo bar"
--password "special key"
然后您可以运行./configtest.py file1.ini file2.ini --password other
,结果值的主机名为 10.2.3.4,用户名为“foo bar”,密码为“其他”。如果您的程序参数已经有了 optparse-definition,那么配置设置的这种变体会派上用场 -> 只需重复使用它,您就可以将命令行中的值与配置文件中的值以及可能的一些全局配置设置链接起来。
作为一种激励,您的配置参数始终会记录在案,并且输入错误的配置参数会尽早出现,就像您可以使用 optparse-instance 预检查您的默认设置文件(架构检查)一样。不利的一面是,在 ini 中不允许使用 cmets,并且配置元素不容易被子结构化。您的解析器本质上仍然是单行的。
【讨论】:
您可能应该使用 argparse 而不是 optionparse -- optionparse 已被弃用。【参考方案8】:我不止一次遇到同样的问题。我喜欢将 python 文件作为设置文件的想法,它简单、优雅,并且所有 python 开发人员都喜欢它。同时并不真正相信 execfile 的想法。
所以我继续创建Converge。
它支持一些高级选项,但它的核心是简单的 python 模块作为设置文件。
就这么简单
创建default_settings.py
,prod_settings.py
pip install converge
import settings
【讨论】:
以上是关于Python 配置文件:有啥文件格式推荐吗? INI格式还合适吗?看起来很老派的主要内容,如果未能解决你的问题,请参考以下文章
Android studio中XML文件调用图片,这样有啥问题?格式吗? 还有就是Android
请问5D2照片格式,RAW和JPEG两种有啥区别吗?哪个更好呢?