Python:读取每个键有多行的配置文件

16 投票
4 回答
27324 浏览
提问于 2025-04-15 19:09

我正在写一个小的数据库测试工具,它会读取配置文件,这些文件里有查询语句和预期的结果,比如:

query         = "SELECT * from cities WHERE name='Unknown';"
count         = 0
level         = 1
name          = "Check for cities whose name should be null"
suggested_fix = "UPDATE cities SET name=NULL WHERE name='Unknown';"

这个方法很好用;我用Python的 string.partition('=') 来分割每一行。

但我遇到的问题是,SQL查询语句太长了。目前我只是把这些查询写成一行,这样看起来很难看,也不方便维护。

我想找到一种优雅的、符合Python风格的方法来读取表达式右边的内容,即使它跨越多行也没关系。

注意:

  • 我的SQL查询可能会包含 = 符号
  • 我不太喜欢在右边内容周围强制加上 " 符号,因为很多现有的文件里没有这个。

补充:

ConfigParser 很不错,但它要求我在多行条目的每一行开头加一个空格或制表符,这可能会很麻烦。

提前谢谢你,

亚当

4 个回答

1

我建议你使用正则表达式……代码可能看起来像这样,给你一个开始的参考:

import re

test="""query = "select * from cities;"
count = 0
multine_query = "select *
from cities
     where name='unknown';"
"""

re_config = re.compile(r'^(\w+)\s*=\s*((?:".[^"]*")|(?:\d+))$', re.M)
for key, value in re_config.findall(test):
    if value.startswith('"'):
        value = value[1:-1]
    else:
        value = int(value)
    print key, '=', repr(value)

这个例子的输出是:

~> python test.py 
query = 'select * from cities;'
count = 0
multine_query = "select *\nfrom cities\n     where name='unknown';"

希望这对你有帮助!

祝好,
Christoph

24

Python的标准库模块ConfigParser默认就支持这个功能。配置文件需要按照一种标准格式来写:

[Long Section]
short: this is a normal line
long: this value continues
    in the next line

上面的配置文件可以用下面的代码来读取:

import ConfigParser
config = ConfigParser.ConfigParser()
config.read('longsections.cfg')
long = config.get('Long Section', 'long')
11

这几乎正是我们决定使用YAML的原因之一。你可以在维基百科上了解更多,或者查看Python的实现文档。另外,你也可以看看JSON,它也是一个不错的选择。YAML相比于configparserjson有一些优点:

  • 人类可读性更强(对于较大的文件,YAML比JSON更好);
  • 可以序列化任意的Python对象(这使得它和pickle一样不太安全,不过在Python的实现中有一个safe_load函数可以缓解这个问题)。这对于像datetime这样的简单对象来说已经很有用了。

为了全面起见,主要的缺点(个人观点)有:

  • Python的实现比JSON的实现慢很多;
  • 在不同平台之间的可移植性不如JSON。

举个例子

import yaml

sql = """
query         : "SELECT * from cities
WHERE name='Unknown';"
count         : 0
level         : 1
name          : "Check for cities whose name should be null"
suggested_fix : "UPDATE cities SET name=NULL WHERE name='Unknown';"
"""

sql_dict = yaml.safe_load(sql)

print(sql_dict['query'])

输出

SELECT * from cities WHERE name='Unknown';

撰写回答