我有配置文件,
[local]
variable1 : val1 ;#comment1
variable2 : val2 ;#comment2
像这样的代码只读取密钥的值:
class Config(object):
def __init__(self):
self.config = ConfigParser.ConfigParser()
self.config.read('config.py')
def get_path(self):
return self.config.get('local', 'variable1')
if __name__ == '__main__':
c = Config()
print c.get_path()
但我也想阅读评论以及价值,这方面的任何建议都会非常有帮助。
答案 0 :(得分:8)
在您的具体情况下,这很容易,因为#
仅在它开始一行时用作注释字符。因此variable1的值将为"val1 #comment1"
。我想你使用这样的东西,只是不那么脆弱了:
val1_line = c.get('local', 'var1')
val1, comment = val1_line.split(' #')
如果需要'评论'的值,可能是不是一个正确的评论?考虑为“评论”添加显式键,如下所示:
[local]
var1: 108.5j
var1_comment: remember, the flux capacitor capacitance is imaginary!
答案 1 :(得分:2)
根据ConfigParser module文档,
配置文件可能包含以特定为前缀的注释 字符(#和;)。评论可能会出现在其他方面 空行,或者可以在包含值或部分的行中输入 名。在后一种情况下,它们需要前面有一个空格 要被识别为评论的字符。 (为了向后兼容, 只要 ;开始内联评论,而#不开始。)
如果要阅读带有值的“注释”,可以省略;
字符前面的空格或使用#
。但在这种情况下,字符串comment1
和comment2
将成为值的一部分,不再被视为注释。
更好的方法是使用不同的属性名称,例如variable1_comment
,或者在专用于注释的配置中定义另一个部分:
[local]
variable1 = value1
[comments]
variable1 = comment1
第一个解决方案要求您使用另一个生成新密钥(即从variable1_comment
计算variable1
),另一个允许您使用相同的密钥定位配置文件中的不同部分。
从Python 2.7.2开始,如果您使用#
字符,总是可以沿着行阅读评论。正如文档所说,这是为了向后兼容。以下代码应该顺利运行:
config = ConfigParser.ConfigParser()
config.read('config.ini')
assert config.get('local', 'variable1') == 'value1'
assert config.get('local', 'variable2') == 'value2 # comment2'
以下config.ini
文件:
[local]
variable1 = value1 ; comment1
variable2 = value2 # comment2
如果您采用此解决方案,请记得手动解析get()
的结果以获取值和评论。
答案 2 :(得分:2)
您唯一的解决方案是编写另一个ConfigParser
来覆盖方法_read()
。在ConfigParser
中,您应删除有关删除评论的所有检查。这是一个危险的解决方案,但应该可行。
class ValuesWithCommentsConfigParser(ConfigParser.ConfigParser):
def _read(self, fp, fpname):
from ConfigParser import DEFAULTSECT, MissingSectionHeaderError, ParsingError
cursect = None # None, or a dictionary
optname = None
lineno = 0
e = None # None, or an exception
while True:
line = fp.readline()
if not line:
break
lineno = lineno + 1
# comment or blank line?
if line.strip() == '' or line[0] in '#;':
continue
if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR":
# no leading whitespace
continue
# continuation line?
if line[0].isspace() and cursect is not None and optname:
value = line.strip()
if value:
cursect[optname].append(value)
# a section header or option header?
else:
# is it a section header?
mo = self.SECTCRE.match(line)
if mo:
sectname = mo.group('header')
if sectname in self._sections:
cursect = self._sections[sectname]
elif sectname == DEFAULTSECT:
cursect = self._defaults
else:
cursect = self._dict()
cursect['__name__'] = sectname
self._sections[sectname] = cursect
# So sections can't start with a continuation line
optname = None
# no section header in the file?
elif cursect is None:
raise MissingSectionHeaderError(fpname, lineno, line)
# an option line?
else:
mo = self._optcre.match(line)
if mo:
optname, vi, optval = mo.group('option', 'vi', 'value')
optname = self.optionxform(optname.rstrip())
# This check is fine because the OPTCRE cannot
# match if it would set optval to None
if optval is not None:
optval = optval.strip()
# allow empty values
if optval == '""':
optval = ''
cursect[optname] = [optval]
else:
# valueless option handling
cursect[optname] = optval
else:
# a non-fatal parsing error occurred. set up the
# exception but keep going. the exception will be
# raised at the end of the file and will contain a
# list of all bogus lines
if not e:
e = ParsingError(fpname)
e.append(lineno, repr(line))
# if any parsing errors occurred, raise an exception
if e:
raise e
# join the multi-line values collected while reading
all_sections = [self._defaults]
all_sections.extend(self._sections.values())
for options in all_sections:
for name, val in options.items():
if isinstance(val, list):
options[name] = '\n'.join(val)
在ValuesWithCommentsConfigParser
我修复了一些导入并删除了相应的代码部分。
使用previous answer中的相同config.ini
,我可以证明以前的代码是正确的。
config = ValuesWithCommentsConfigParser()
config.read('config.ini')
assert config.get('local', 'variable1') == 'value1 ; comment1'
assert config.get('local', 'variable2') == 'value2 # comment2'
答案 3 :(得分:1)
根据手册: 以'#'开头的行或';'被忽略,可用于提供评论。
所以variable1的值是" val1#comment1"。评论是值的一部分
您可以检查您的配置是否在评论之前输入了
答案 4 :(得分:0)
以防万一有人来。我的情况是我需要读取由 Pascal 应用程序生成的 .ini 文件。那个 configparser 不关心 # 或 ;启动键。 例如 .ini 文件看起来像这样
[KEYTYPE PATTERNS]
##-######=CLAIM
Python 的 configparser 会跳过那个键值对。需要修改 configparser 以不将 # 视为注释
config = configparser.ConfigParser(comment_prefixes="")
config.read("thefile")
我确定我可以将 comment_prefixes 设置为 Pascal 用于评论的任何内容,但没有看到任何,所以我将其设置为空字符串