Использование ConfigParser Python для чтения файла без имени раздела
Я использую ConfigParser для чтения конфигурации времени выполнения скрипта.
Я хотел бы иметь гибкость, не предоставляя имя раздела (есть скрипты, которые достаточно просты; им не нужен "раздел"). ConfigParser будет бросать NoSectionError исключения, и не будет принимать файл.
как я могу сделать ConfigParser просто забрать (key, value) кортежи конфигурационного файла без имен разделов? Например:
key1=val1
key2:val2
Я бы скорее не записывайте в конфигурационный файл.
8 ответов:
Алекс Мартелли при условии, что решение использовать
ConfigParserдля разбора.propertiesфайлы (которые, по-видимому, являются файлами конфигурации без разделов).решение файл-как враппер, который будет автоматически вставлять в раздел манекен, направляясь к
ConfigParser's требования.
просвещенные этот ответ от jterrace, Я придумал такое решение:
- читать весь файл в одну строку
- префикс с именем раздела по умолчанию
- использовать StringIO для имитации файл-как объект
ini_str = '[root]\n' + open(ini_path, 'r').read() ini_fp = StringIO.StringIO(ini_str) config = ConfigParser.RawConfigParser() config.readfp(ini_fp)
EDIT для будущих гуглеров: начиная с Python 3.4+readfpустарел, иStringIOбольше не нужен. Вместо этого мы можем использоватьread_stringнапрямую:with open('config_file') as f: file_content = '[dummy_section]\n' + f.read() config_parser = RawConfigParser() config_parser.read_string(file_content)
вы можете сделать это с помощью одной дополнительной строки кода. (Две строки, если считать
importзаявления.)в python 3, Используйте
itertools.chain()для имитации заголовка раздела дляread_file().from configparser import ConfigParser from itertools import chain parser = ConfigParser() with open("foo.conf") as lines: lines = chain(("[top]",), lines) # This line does the trick. parser.read_file(lines)в python 2, добавьте строку заголовка раздела К данным, которые Вы читаете из вашего файла конфигурации, оберните результат в
StringIO"объект", и передать его вreadfp().from ConfigParser import ConfigParser from StringIO import StringIO parser = ConfigParser() with open("foo.conf") as stream: stream = StringIO("[top]\n" + stream.read()) # This line does the trick. parser.readfp(stream)С подход, ваши настройки конфигурации будут доступны в
parser.items('top').вы могли бы использовать
StringIOв python 3, а также, импортируя его из своего нового дома вioпакет, но обратите внимание, чтоreadfp()является устаревшим в python 3 и поэтому следует избегать.
если вы не возражаете против дополнительной зависимости, вы можете рассмотреть возможность использования TOML парсер вместо ConfigParser.
вы можете использовать библиотеку ConfigObj, чтобы сделать это просто:http://www.voidspace.org.uk/python/configobj.html
Обновлено: найти последний код здесь.
Если вы находитесь под Debian / Ubuntu, вы можете установить этот модуль с помощью диспетчера пакетов:
apt-get install python-configobjпример использования:
from configobj import ConfigObj config = ConfigObj('myConfigFile.ini') config.get('key1') # You will get val1 config.get('key2') # You will get val2
самый простой способ сделать это-использовать CSV-парсер python, на мой взгляд. Вот функция чтения / записи, демонстрирующая этот подход, а также тестовый драйвер. Это должно работать при условии, что значения не могут быть многострочными. :)
import csv import operator def read_properties(filename): """ Reads a given properties file with each line of the format key=value. Returns a dictionary containing the pairs. Keyword arguments: filename -- the name of the file to be read """ result={ } with open(filename, "rb") as csvfile: reader = csv.reader(csvfile, delimiter='=', escapechar='\', quoting=csv.QUOTE_NONE) for row in reader: if len(row) != 2: raise csv.Error("Too many fields on row with contents: "+str(row)) result[row[0]] = row[1] return result def write_properties(filename,dictionary): """ Writes the provided dictionary in key-sorted order to a properties file with each line of the format key=value Keyword arguments: filename -- the name of the file to be written dictionary -- a dictionary containing the key/value pairs. """ with open(filename, "wb") as csvfile: writer = csv.writer(csvfile, delimiter='=', escapechar='\', quoting=csv.QUOTE_NONE) for key, value in sorted(dictionary.items(), key=operator.itemgetter(0)): writer.writerow([ key, value]) def main(): data={ "Hello": "5+5=10", "World": "Snausage", "Awesome": "Possum" } filename="test.properties" write_properties(filename,data) newdata=read_properties(filename) print "Read in: " print newdata print contents="" with open(filename, 'rb') as propfile: contents=propfile.read() print "File contents:" print contents print ["Failure!", "Success!"][data == newdata] return if __name__ == '__main__': main()
столкнувшись с этой проблемой сам, я написал полную оболочку для ConfigParser (версия в Python 2), которая может читать и записывать файлы без разделов прозрачно, на основе подхода Алекса Мартелли, связанного с принятым ответом. Это должна быть замена для любого использования ConfigParser. Разместите его в случае, если кто-то нуждается в этом находит эту страницу.
import ConfigParser import StringIO class SectionlessConfigParser(ConfigParser.RawConfigParser): """ Extends ConfigParser to allow files without sections. This is done by wrapping read files and prepending them with a placeholder section, which defaults to '__config__' """ def __init__(self, *args, **kwargs): default_section = kwargs.pop('default_section', None) ConfigParser.RawConfigParser.__init__(self, *args, **kwargs) self._default_section = None self.set_default_section(default_section or '__config__') def get_default_section(self): return self._default_section def set_default_section(self, section): self.add_section(section) # move all values from the previous default section to the new one try: default_section_items = self.items(self._default_section) self.remove_section(self._default_section) except ConfigParser.NoSectionError: pass else: for (key, value) in default_section_items: self.set(section, key, value) self._default_section = section def read(self, filenames): if isinstance(filenames, basestring): filenames = [filenames] read_ok = [] for filename in filenames: try: with open(filename) as fp: self.readfp(fp) except IOError: continue else: read_ok.append(filename) return read_ok def readfp(self, fp, *args, **kwargs): stream = StringIO() try: stream.name = fp.name except AttributeError: pass stream.write('[' + self._default_section + ']\n') stream.write(fp.read()) stream.seek(0, 0) return ConfigParser.RawConfigParser.readfp(self, stream, *args, **kwargs) def write(self, fp): # Write the items from the default section manually and then remove them # from the data. They'll be re-added later. try: default_section_items = self.items(self._default_section) self.remove_section(self._default_section) for (key, value) in default_section_items: fp.write("{0} = {1}\n".format(key, value)) fp.write("\n") except ConfigParser.NoSectionError: pass ConfigParser.RawConfigParser.write(self, fp) self.add_section(self._default_section) for (key, value) in default_section_items: self.set(self._default_section, key, value)
в ответе Blueicefield упоминается configobj, но исходная библиотека поддерживает только Python 2. Теперь он имеет Python 3+ совместимый порт:
https://github.com/DiffSK/configobj
API не изменились, смотрите это doc.
configobj lib может помочь в случае
KEY="value"from configobj import ConfigObj cfg = ConfigObj('/home/.aws/config') access_key_id = cfg['aws_access_key_id'] secret_access_key = cfg['aws_secret_access_key']
Comments