Python Config parser читает комментарий вместе со значением
у меня есть файл config,
[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()
но я также хочу прочитать комментарий, присутствующий вместе со значением, любые предложения в этом отношении будут очень полезны.
4 ответов
ваши единственные решения-написать другой 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
я исправил некоторые импорта и удалил соответствующие разделы кода.
используя то же самое config.ini
от меня предыдущий ответ, я могу доказать, что предыдущий код является правильным.
config = ValuesWithCommentsConfigParser()
config.read('config.ini')
assert config.get('local', 'variable1') == 'value1 ; comment1'
assert config.get('local', 'variable2') == 'value2 # comment2'
увы, это нелегко сделать в общем случае. Комментарии должно игнорируется парсером.
в вашем конкретном случае, это легко, потому что #
служит символом комментария, только если он начинает строку. Таким образом, значение 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!
Accordiing к модуль ConfigParser документация
файлы конфигурации могут содержать комментарии с префиксом символы ( # , и). Комментарии могут появляться самостоятельно в противном случае пустая строка или может быть введена в строки, содержащие значения или раздел имена. В последнем случае им должны предшествовать пробелы характер должен быть распознан как комментарий. (Для обратной совместимости, только; запускает встроенный комментарий, пока # не.)
если вы хотите прочитать "комментарий" со значением, вы можете опустить пробелы перед ;
символ или использовать #
. Но в этом случае строки comment1
и comment2
стать частью значения и больше не считаются комментариями.
лучшим подходом было бы использовать другое имя свойства, например variable1_comment
, или определить другой раздел в конфигурации, посвященные комментариев:
[local]
variable1 = value1
[comments]
variable1 = comment1
в первое решение требует, чтобы вы создали новый ключ, используя другой (т. е. compute 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'
для следующих :
[local]
variable1 = value1 ; comment1
variable2 = value2 # comment2
если вы принимаете это решение, не забудьте вручную проанализировать результат get()
для значений и комментариев.
по данным руководства: Строки, начинающиеся с '#' или ';' игнорируются и могут использоваться для предоставления комментариев.
таким образом, значение variable1 - "val1 #comment1".Комментарий является частью значения
вы можете проверить свою конфигурацию, ставите ли вы ввод перед своим комментарием