Estoy usando ConfigParser
para leer la configuración de tiempo de ejecución de un script.
Me gustaría tener la flexibilidad de no proporcionar un nombre de sección (hay scripts que son lo suficientemente simples; no necesitan una 'sección'). ConfigParser
lanzará una NoSectionError
excepción y no aceptará el archivo.
¿Cómo puedo hacer que ConfigParser simplemente recupere las (key, value)
tuplas de un archivo de configuración sin nombres de sección?
Por ejemplo:
key1=val1
key2:val2
Preferiría no escribir en el archivo de configuración.
python
parsing
configuration-files
Escualo
fuente
fuente
Respuestas:
Alex Martelli proporcionó una solución para
ConfigParser
analizar.properties
archivos (que aparentemente son archivos de configuración sin sección).Su solución es un contenedor similar a un archivo que insertará automáticamente un encabezado de sección ficticia para satisfacer
ConfigParser
los requisitos.fuente
Iluminado por esta respuesta de jterrace , se me ocurre esta solución:
ini_str = '[root]\n' + open(ini_path, 'r').read() ini_fp = StringIO.StringIO(ini_str) config = ConfigParser.RawConfigParser() config.readfp(ini_fp)
EDITAR para futuros usuarios de Google: a partir de Python 3.4+
readfp
está obsoleto yStringIO
ya no es necesario. En su lugar, podemos usarread_string
directamente:with open('config_file') as f: file_content = '[dummy_section]\n' + f.read() config_parser = ConfigParser.RawConfigParser() config_parser.read_string(file_content)
fuente
Puede hacer esto en una sola línea de código.
En Python 3, anteponga un encabezado de sección falso a los datos de su archivo de configuración y páselo a
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.
También puede usar
itertools.chain()
para simular un encabezado de sección pararead_file()
. Esto podría ser más eficiente en memoria que el enfoque anterior, lo que podría ser útil si tiene archivos de configuración grandes en un entorno de ejecución restringido.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)
En Python 2, anteponga un encabezado de sección falso a los datos de su archivo de configuración, envuelva el resultado en un
StringIO
objeto y páselo areadfp()
.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)
Con cualquiera de estos enfoques, su configuración de configuración estará disponible en
parser.items('top')
.También podría usar StringIO en Python 3, quizás por compatibilidad con los intérpretes de Python nuevos y antiguos, pero tenga en cuenta que ahora vive en el
io
paquete yreadfp()
ahora está en desuso.Alternativamente, podría considerar usar un analizador TOML en lugar de ConfigParser.
fuente
Puede usar la biblioteca ConfigObj para hacerlo simplemente: http://www.voidspace.org.uk/python/configobj.html
Actualizado: encuentre el código más reciente aquí .
Si está en Debian / Ubuntu, puede instalar este módulo usando su administrador de paquetes:
Un ejemplo de uso:
from configobj import ConfigObj config = ConfigObj('myConfigFile.ini') config.get('key1') # You will get val1 config.get('key2') # You will get val2
fuente
La forma más fácil de hacer esto es usar el analizador CSV de Python, en mi opinión. Aquí hay una función de lectura / escritura que demuestra este enfoque, así como un controlador de prueba. Esto debería funcionar siempre que no se permita que los valores sean de varias líneas. :)
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()
fuente
csv
módulo para resolverConfigParser
quejas comunes . Fácilmente generalizado y hecho para ser compatible con Python 2 y 3 .Habiéndome encontrado con este problema, escribí un contenedor completo para ConfigParser (la versión en Python 2) que puede leer y escribir archivos sin secciones de forma transparente, según el enfoque de Alex Martelli vinculado a la respuesta aceptada. Debería ser un reemplazo directo de cualquier uso de ConfigParser. Publicarlo en caso de que alguien que lo necesite encuentre 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)
fuente
La respuesta de Blueicefield mencionó configobj, pero la biblioteca original solo es compatible con Python 2. Ahora tiene un puerto compatible con Python 3+:
https://github.com/DiffSK/configobj
Las API no han cambiado, consulte su documento .
fuente