Estou usando ConfigParser
para ler a configuração de tempo de execução de um script.
Eu gostaria de ter a flexibilidade de não fornecer um nome de seção (existem scripts que são simples; eles não precisam de uma 'seção'). ConfigParser
lançará uma NoSectionError
exceção e não aceitará o arquivo.
Como posso fazer com que o ConfigParser simplesmente recupere as (key, value)
tuplas de um arquivo de configuração sem nomes de seção?
Por exemplo:
key1=val1
key2:val2
Prefiro não gravar no arquivo de configuração.
python
parsing
configuration-files
Escualo
fonte
fonte
Respostas:
Alex Martelli forneceu uma solução para usar
ConfigParser
para analisar.properties
arquivos (que aparentemente são arquivos de configuração sem seção).Sua solução é um invólucro semelhante a um arquivo que irá inserir automagicamente um cabeçalho de seção fictício para satisfazer
ConfigParser
os requisitos de.fonte
Iluminado por esta resposta de jterrace , eu vim com esta solução:
ini_str = '[root]\n' + open(ini_path, 'r').read() ini_fp = StringIO.StringIO(ini_str) config = ConfigParser.RawConfigParser() config.readfp(ini_fp)
EDIT para futuros googlers: a partir do Python 3.4+
readfp
se tornou obsoleto eStringIO
não é mais necessário. Em vez disso, podemos usarread_string
diretamente:with open('config_file') as f: file_content = '[dummy_section]\n' + f.read() config_parser = ConfigParser.RawConfigParser() config_parser.read_string(file_content)
fonte
Você pode fazer isso em uma única linha de código.
No python 3, acrescente um cabeçalho de seção falso aos dados do arquivo de configuração e passe-o para
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.
Você também pode usar
itertools.chain()
para simular um cabeçalho de seção pararead_file()
. Isso pode ser mais eficiente em termos de memória do que a abordagem acima, o que pode ser útil se você tiver grandes arquivos de configuração em um ambiente de tempo de execução restrito.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)
No python 2, acrescente um cabeçalho de seção falso aos dados do arquivo de configuração, envolva o resultado em um
StringIO
objeto e passe-o parareadfp()
.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)
Com qualquer uma dessas abordagens, suas configurações estarão disponíveis em
parser.items('top')
.Você também pode usar StringIO no python 3, talvez para compatibilidade com interpretadores python novos e antigos, mas observe que agora ele está no
io
pacote ereadfp()
está obsoleto.Como alternativa, você pode considerar o uso de um analisador TOML em vez do ConfigParser.
fonte
Você pode usar a biblioteca ConfigObj para fazer isso simplesmente: http://www.voidspace.org.uk/python/configobj.html
Atualizado: Encontre o código mais recente aqui .
Se você estiver no Debian / Ubuntu, pode instalar este módulo usando seu gerenciador de pacotes:
Um exemplo de uso:
from configobj import ConfigObj config = ConfigObj('myConfigFile.ini') config.get('key1') # You will get val1 config.get('key2') # You will get val2
fonte
A maneira mais fácil de fazer isso é usar o analisador CSV do python, na minha opinião. Aqui está uma função de leitura / gravação que demonstra essa abordagem, bem como um driver de teste. Isso deve funcionar, desde que os valores não possam ser multilinhas. :)
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()
fonte
csv
módulo para resolverConfigParser
reclamações comuns . Facilmente generalizado mais e feito para ser compatível com Python 2 e 3 .Tendo enfrentado esse problema sozinho, escrevi um wrapper completo para ConfigParser (a versão em Python 2) que pode ler e gravar arquivos sem seções de forma transparente, com base na abordagem de Alex Martelli vinculada à resposta aceita. Deve ser um substituto imediato para qualquer uso do ConfigParser. Postar no caso de alguém que precise encontrar esta página.
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)
fonte
A resposta de Blueicefield mencionou configobj, mas a lib original só oferece suporte a Python 2. Ela agora tem uma porta compatível com Python 3+:
https://github.com/DiffSK/configobj
APIs não mudaram, veja seu doc .
fonte