Python:如何在省略注释的同时从属性文件创建字典
Posted
技术标签:
【中文标题】Python:如何在省略注释的同时从属性文件创建字典【英文标题】:Python: How to create a dictionary from properties file while omitting comments 【发布时间】:2013-11-16 22:46:10 【问题描述】:我已经在这里搜索了一段时间的答案,但还没有找到,所以希望这不是一个骗局。
我有一个属性文件,其中大部分包含键=值对,但也包含#cmets。我需要把它放在字典里,这样我就可以随意获取值了。在没有#cmets 的文件中,以下内容完美运行。
myprops = dict(line.strip().split('=') for line in open('/Path/filename.properties'))
print myprops['key']
但当有 cmets 存在时,情况并非如此。如果存在#comment
,字典会说
"ValueError: dictionary update sequence element #x has length 1, 2 is required"
我已经尝试将字典创建包装在条件句中
if not line.startswith('#'):
但我似乎无法让它发挥作用。建议?谢谢!
【问题讨论】:
所以说清楚,你试过dict(line.strip().split('=') for line in open('/Path/filename.properties') if not line.startswith('#'))
?
我没有这样尝试过,但确实有效。谢谢!
我可能说得太早了。我认为错误只是由于注释行引起的。也有空行。它给出了同样的错误。我以为line.strip()
会跳过所有的空白行。
【参考方案1】:
为了解决您对空白行的最新限制,我会尝试以下方法:
myprops =
with open('filename.properties', 'r') as f:
for line in f:
line = line.rstrip() #removes trailing whitespace and '\n' chars
if "=" not in line: continue #skips blanks and comments w/o =
if line.startswith("#"): continue #skips comments which contain =
k, v = line.split("=", 1)
myprops[k] = v
它非常清晰,并且很容易添加额外的约束,而使用 dict 推导式会变得非常臃肿。但是,您总是可以很好地格式化它
myprops = dict(line.strip().split('=')
for line in open('/Path/filename.properties'))
if ("=" in line and
not line.startswith("#") and
<extra constraint> and
<another extra constraint>))
【讨论】:
【参考方案2】:您应该只使用内置的 configparser
来读取 ini 样式的配置文件。它允许 cmets 默认使用 ;
和 #
,所以它应该适合你。
对于.properties
文件,您可能需要进行一些技巧,因为 configparser 通常需要部分名称。您可以通过在阅读时添加一个虚拟部分来轻松做到这一点:
>>> from configparser import ConfigParser
>>> config = ConfigParser()
>>> with open(r'C:\Users\poke\Desktop\test.properties') as f:
config.read_string('[config]\n' + f.read())
>>> for k, v in config['config'].items():
print(k, v)
foo bar
bar baz
baz foo
(使用与 mtitan8 相同的示例文件)
对于 Python 2,请改用 from ConfigParser import ConfigParser
。
【讨论】:
这很酷。谢谢。我的属性文件不是带有括号部分名称(如“[config]”)的 windows 样式。没有这些,ConfigParser 可以工作吗?谢谢! 是的,这基本上就是我在示例代码中这样做的原因。我的test.properties
也没有任何section,所以在读取文件时,我只是在文件顶部添加了一个dummy section,这样configparser就不会抱怨了。
我必须做import ConfigParser
。 from configparser import ConfigParser
给我一个导入错误。不过,无论如何,我在下一行config = ConfigParser()
上收到一个错误,指出“模块”对象不可调用。如果它对这个解决方案有影响,我在 Python 2.7 上。谢谢。
对,你需要在 Python 2 中使用 from ConfigParser import ConfigParser
,因为那时模块名称还没有在 lowercase 中。
如果您的属性文件包含相同的属性但大小写不同,上述方法将不起作用。例如一个属性是foo=bar
,而另一个属性是Foo=bar
。你会得到一个错误option 'foo' in section 'config' already exists
【参考方案3】:
给定一个属性文件 test.txt
,正如你所描述的:
foo=bar
#skip me
bar=baz
baz=foo
#skip me too!
您可以执行以下操作:
>>> D = dict( l.rstrip().split('=') for l in open("test.txt")
if not l.startswith("#") )
>>> D
'baz': 'foo', 'foo': 'bar', 'bar': 'baz'
这看起来就像你说你尝试使用 if not line.startswith('#')
的代码,所以希望这个工作示例能帮助你查明错误。
【讨论】:
【参考方案4】:为什么要把它强行写成一行?两周后,用户将在某处放置一个空格,或者想要使用引号,而您必须展开代码。现在只需创建一个函数来处理输入并完成它。这也意味着您可以使用单元测试来确保它正常工作并继续工作。
鉴于此输入:
foo=bar
#skip me
bar=baz
baz=foo
#skip me too!
下面的代码可以很好地处理这一切。
import sys
def parse_line(input):
key, value = input.split('=')
key = key.strip() # handles key = value as well as key=value
value = value.strip()
return key, value
if __name__ == '__main__':
data =
with open(sys.argv[1]) as fp:
for line in fp:
line = line.strip()
if not line or line.startswith('#'):
continue
key, value = parse_line(input)
data[key] = value
print data
顺便说一句,我喜欢 poke 关于使用 ConfigParser 的建议。但是添加一个部分的技巧可能对每个人都有效,也可能不适用。
如果您想将注释检查移到 parse_line() 函数中,您可以返回 None、None 并在将键/值对放入字典之前进行检查。
【讨论】:
【参考方案5】:line.startswith('#')
不应该更好地阅读line.strip().startswith('#')
?
dict(line.strip().split('=') for line in open('/Path/filename.properties')
if not line.strip().startswith('#'))
【讨论】:
这没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方发表评论 - 您可以随时评论自己的帖子,一旦您有足够的reputation,您就可以comment on any post。 对,我试图改进答案,但不允许我添加评论,所以我宁愿按照允许的方式而不是不允许的方式。【参考方案6】:没有一个解决方案考虑到该值可以包含=
符号。
想象以下文件:
baz=foo
foo="foo=bar"
bar=baz
因此,我建议使用以下代码:
>>> D = dict( l.rstrip().split('=', maxsplit=1) for l in open("test.txt") if not l.startswith("#") )
>>> D
'baz': 'foo', 'foo': '"foo=bar"', 'bar': 'baz'
【讨论】:
以上是关于Python:如何在省略注释的同时从属性文件创建字典的主要内容,如果未能解决你的问题,请参考以下文章
如何从接口中省略一个属性,而不是 TypeScript 中的类型?
Python3 基础语法:编码标识符python保留字注释多行语句等介绍