带有python中键值对列表的配置文件

Posted

技术标签:

【中文标题】带有python中键值对列表的配置文件【英文标题】:Configuration file with list of key-value pairs in python 【发布时间】:2010-09-16 06:14:39 【问题描述】:

我有一个 python 脚本,它分析一组错误消息并检查每条消息是否与某个模式(正则表达式)匹配,以便对这些消息进行分组。例如,“文件 x 不存在”和“文件 y 不存在”将匹配“文件 .* 不存在”并被视为两次出现的“文件未找到”类别。

随着模式和类别的数量越来越多,我想把这些“正则表达式/显示字符串”放在一个配置文件中,基本上是某种字典序列化。

我希望这个文件可以手动编辑,所以我放弃了任何形式的二进制序列化,而且我宁愿不使用 xml 序列化来避免字符转义的问题(& 等等...)。

您知道什么是完成此任务的好方法吗?

更新:感谢 Daren Thomas 和 Federico Ramponi,但我不能拥有包含任意代码的外部 python 文件。

【问题讨论】:

【参考方案1】:

你有两个不错的选择:

    Python 标准配置文件格式 使用ConfigParser YAML 使用像 PyYAML 这样的库

标准的 Python 配置文件看起来像带有 [sections]key : valuekey = value 对的 INI 文件。这种格式的优点是:

无需第三方库 简单、熟悉的文件格式。

YAML 的不同之处在于它被设计为一种对人类友好的数据序列化格式,而不是专门为配置而设计的。它非常易读,并为您提供了几种不同的方式来表示相同的数据。对于您的问题,您可以创建一个如下所示的 YAML 文件:

file .* does not exist : file not found
user .* not found : authorization error

或者像这样:

 file .* does not exist: file not found,
  user .* not found: authorization error 

使用 PyYAML 再简单不过了:

import yaml

errors = yaml.load(open('my.yaml'))

此时errors 是具有预期格式的Python 字典。 YAML 能够表示的不仅仅是字典:如果您更喜欢对列表,请使用以下格式:

-
  - file .* does not exist 
  - file not found
-
  - user .* not found
  - authorization error

或者

[ [file .* does not exist, file not found],
  [user .* not found, authorization error]]

yaml.load 被调用时会产生一个列表。

YAML 的一个优点是您可以使用它将现有的硬编码数据导出到文件中以创建初始版本,而不是通过剪切/粘贴加上一堆查找/替换来将数据放入正确的格式。

熟悉 YAML 格式需要更多时间,但使用 PyYAML 比使用 ConfigParser 更简单,其优点是您有更多关于如何使用 YAML 表示数据的选项。

其中任何一个听起来都适合您当前的需求,ConfigParser 将更容易开始,而 YAML 在未来为您提供更多灵活性,如果您的需求扩大。

祝你好运!

【讨论】:

JSON 作为配置文件的表示法有什么问题? JSON 也应该可以,我只是更熟悉 YAML。当然2.6有新的json模块,很方便。 JSON 比 XML 更好,但它的波浪形括号和所有字符串(包括键)都被引用的要求使其不太人性化。 python 需要外部依赖来支持 YAML 真的不太好。 @S.Lott 如果您将 JSON 用于您的配置文件,请尽情享受无法评论的乐趣!【参考方案2】:

我通常按照达伦的建议做,只需将您的配置文件设为 Python 脚本即可:

patterns = 
    'file .* does not exist': 'file not found',
    'user .* not found': 'authorization error',

那么你可以把它当作:

import config

for pattern in config.patterns:
    if re.search(pattern, log_message):
        print config.patterns[pattern]

顺便说一下,这就是 Django 对他们的设置文件所做的事情。

【讨论】:

【参考方案3】:

我有时只是编写一个名为config.py 的python 模块(即文件)或具有以下内容的东西:

config = 
    'name': 'hello',
    'see?': 'world'

然后可以像这样“读取”:

from config import config
config['name']
config['see?']

简单。

【讨论】:

很好,但问题中的“字典”一词有些误导。一个正则表达式不能作为一个键,他需要的是一个情侣列表...... @Federico:正则表达式模式可以是键:patterns = 'file .* doesn't exist': 'file not found', 'user .* not found': '授权错误', 好的 davraamides,但你应该如何使用它?我更喜欢类似:for (regexp,m) in messages: if regexp.match(string): print m @Federico:与您的示例非常相似:for pattern, msg in config.patterns: if re.search(pattern, string): print msg【参考方案4】:

如果您是唯一有权访问配置文件的人,则可以使用简单的低级解决方案。将文本文件中的“字典”保存为元组列表(正则表达式,消息),就像它是 python 表达式一样:

[
("file .* does not exist", "file not found"),
("user .* not authorized", "authorization error")
]
在您的代码中,加载它,然后对其进行评估,并在结果中编译正则表达式:
f = open("messages.py")
messages = eval(f.read()) # caution: you must be sure of what's in that file
f.close()
messages = [(re.compile(r), m) for (r,m) in messages]
最后得到一个元组列表(compiled_regexp,message)。

【讨论】:

这很好用。语法易于编写和验证。 “如果有人将危险代码放入配置文件怎么办?”问题很疯狂。如果您有任何疑问,请与有权访问配置的人员交谈。 为什么要麻烦评估?只需将您的配置文件设为 python 脚本并导入即可。 是的,是的,读完帖子后,现在我想我会坚持“导入脚本”的解决方案……【参考方案5】:

我听说ConfigObj 比 ConfigParser 更容易使用。它被很多大型项目使用,IPython、Trac、Turbogears 等......

来自他们的introduction:

ConfigObj 是一个简单但功能强大的配置文件读取器和写入器:一个 ini 文件往返程序。它的主要特点是非常易于使用,具有简单的程序员界面和简单的配置文件语法。它还有很多其他功能:

嵌套部分(子部分),到任何级别 列出值 多行值 字符串插值(替换) 与强大的验证系统集成 包括自动类型检查/转换 重复部分 并允许使用默认值 在写出配置文件时,ConfigObj 会保留所有 cmets 以及成员和节的顺序 许多用于处理配置文件的有用方法和选项(例如“重新加载”方法) 完整的 Unicode 支持

【讨论】:

与 python 自己的 ConfigParser 相比的一个优势是不需要部分。【参考方案6】:

我认为您想要标准库中的ConfigParser 模块。它读取和写入 INI 样式文件。我链接到的标准文档中的示例和文档非常全面。

【讨论】:

以上是关于带有python中键值对列表的配置文件的主要内容,如果未能解决你的问题,请参考以下文章

如何在不干扰 iOS 中键值对序列的情况下读写 json 文件?

反转字典中键值对的顺序(Python)[重复]

替换对象中键值对的Python函数返回意外输出[重复]

Python中删除字典中键值对的方法

C 语言文件操作 ( 配置文件读写 | 写出或更新配置文件 | 追加键值对数据 | 更新键值对数据 )

Python configparser的使用 读取配置文件