Я использую ConfigParser
для чтения конфигурации выполнения сценария.
Я хотел бы иметь возможность не указывать имя раздела (есть сценарии, которые достаточно просты; им не нужен «раздел»). ConfigParser
вызовет NoSectionError
исключение и не примет файл.
Как я могу заставить ConfigParser просто извлекать (key, value)
кортежи из файла конфигурации без имен разделов?
Например:
key1=val1
key2:val2
Я бы предпочел не писать в файл конфигурации.
python
parsing
configuration-files
Escualo
источник
источник
Ответы:
Алекс Мартелли предоставил решение для использования
ConfigParser
для анализа.properties
файлов (которые, по-видимому, представляют собой файлы конфигурации без разделов).Его решение представляет собой файловую оболочку, которая автоматически вставляет фиктивный заголовок раздела в соответствии
ConfigParser
с требованиями пользователя.источник
Просвещенный этим ответом jterrace , я придумал следующее решение:
ini_str = '[root]\n' + open(ini_path, 'r').read() ini_fp = StringIO.StringIO(ini_str) config = ConfigParser.RawConfigParser() config.readfp(ini_fp)
EDIT для будущих Googlers: на Python 3.4+
readfp
является устаревшим, иStringIO
не нужен. Вместо этого мы можем использоватьread_string
напрямую:with open('config_file') as f: file_content = '[dummy_section]\n' + f.read() config_parser = ConfigParser.RawConfigParser() config_parser.read_string(file_content)
источник
Вы можете сделать это одной строкой кода.
В python 3 добавьте поддельный заголовок раздела к данным файла конфигурации и передайте его в
read_string()
.from configparser import ConfigParser parser = ConfigParser() with open("foo.conf") as stream: parser.read_string("[top]\n" + stream.read()) # This line does the trick.
Вы также можете использовать
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, возможно, для совместимости как со старыми, так и с новыми интерпретаторами python, но обратите внимание, что теперь он находится в
io
пакете иreadfp()
устарел.В качестве альтернативы вы можете рассмотреть возможность использования парсера TOML вместо ConfigParser.
источник
Для этого вы можете использовать библиотеку ConfigObj: http://www.voidspace.org.uk/python/configobj.html
Обновлено: последний код можно найти здесь .
Если вы находитесь под Debian / Ubuntu, вы можете установить этот модуль с помощью диспетчера пакетов:
Пример использования:
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()
источник
csv
модуля для решения распространенныхConfigParser
жалоб. Легко обобщить и сделать совместимыми с Python 2 и 3 .Сам столкнувшись с этой проблемой, я написал полную оболочку для 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 не изменились, см. Документ .
источник