Python:读取每个键多行的配置文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2245761/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Python: Read configuration file with multiple lines per key
提问by Adam Matan
I am writing a small DB test suite, which reads configuration files with queries and expected results, e.g.:
我正在编写一个小型数据库测试套件,它读取带有查询和预期结果的配置文件,例如:
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';"
This works well; I divide each line using Python's string.partition('=')
.
这很好用;我使用 Python 的string.partition('=')
.
My problem is very long SQL queries. Currently, I just paste these queries as a one-liner, which is ugly and unmaintainable.
我的问题是很长的 SQL 查询。目前,我只是将这些查询粘贴为单行,这是丑陋且不可维护的。
I want to find an elegant, Pythonic way to read the right of an expression, even if spans over many lines.
我想找到一种优雅的 Pythonic 方式来读取表达式的右侧,即使跨越多行也是如此。
Notes:
笔记:
- my SQL queries might contain the
=
- I don't fancy the idea of forcing
"
s around the right hand side, because there are many existing files without it.
- 我的 SQL 查询可能包含
=
- 我不喜欢在
"
右手边强制s的想法,因为有许多现有文件没有它。
EDIT:
编辑:
ConfigParseris great, but it forces me to add a space or tab at the beginning of every line in a multiline entry. This might be a great pain.
ConfigParser很棒,但它迫使我在多行条目的每一行的开头添加一个空格或制表符。这可能是一个很大的痛苦。
Thanks in advance,
提前致谢,
Adam
亚当
采纳答案by stephan
This is almost exactly the use-case that made us switch to YAML(Wikipedia, python implementation, documentation; you might want to look at JSONas an alternative). YAML has some advantages over configparser
or json
:
这几乎正是让我们切换到YAML的用例(维基百科、python 实现、文档;您可能希望将JSON视为替代方案)。YAML 比configparser
or有一些优势json
:
- human readability (better than JSON for larger files);
- can serialize arbitrary python objects (which makes it as un-safe as
pickle
, but there is asafe_load
function in the python implementation to alleviate this issue). This is already useful for something as simple as adatetime
object.
- 人类可读性(对于较大的文件比 JSON 更好);
- 可以序列化任意的 python 对象(这使它像 一样不安全
pickle
,但是safe_load
python 实现中有一个函数可以缓解这个问题)。这对于像datetime
对象这样简单的东西已经很有用了。
For completeness sake, the main disadvantages (IMO):
为了完整起见,主要缺点(IMO):
- Python implementation by an order of magnitude slower than JSON implementation;
- less portable across platforms than JSON.
- Python 实现比 JSON 实现慢一个数量级;
- 跨平台的可移植性不如 JSON。
For example
例如
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'])
prints
印刷
SELECT * from cities WHERE name='Unknown';
回答by Tendayi Mawushe
The Python standard library module ConfigParsersupports this by default. The configuration file has to be in a standard format:
默认情况下,Python 标准库模块ConfigParser支持此功能。配置文件必须采用标准格式:
[Long Section]
short: this is a normal line
long: this value continues
in the next line
The configuration file above could be read with the following code:
上面的配置文件可以用下面的代码读取:
import ConfigParser
config = ConfigParser.ConfigParser()
config.read('longsections.cfg')
long = config.get('Long Section', 'long')
回答by tux21b
I would you suggest to use a regular expression... The code might look like this to give you are start:
我建议您使用正则表达式...代码可能如下所示,以便您开始:
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)
The output of this example is:
这个例子的输出是:
~> python test.py
query = 'select * from cities;'
count = 0
multine_query = "select *\nfrom cities\n where name='unknown';"
Hope that helps!
希望有帮助!
Regards, Christoph
问候, 克里斯托夫