parser - load json config python
analizando el archivo.properties en Python (9)
¡HURRA! otra version
Basado en esta respuesta (la adición usa un dict
, with
declaración y admite el carácter %
)
import ConfigParser
import StringIO
import os
def read_properties_file(file_path):
with open(file_path) as f:
config = StringIO.StringIO()
config.write(''[dummy_section]/n'')
config.write(f.read().replace(''%'', ''%%''))
config.seek(0, os.SEEK_SET)
cp = ConfigParser.SafeConfigParser()
cp.readfp(config)
return dict(cp.items(''dummy_section''))
Uso
props = read_properties_file(''/tmp/database.properties'')
# It will raise if `name` is not in the properties file
name = props[''name'']
# And if you deal with optional settings, use:
connection_string = props.get(''connection-string'')
password = props.get(''password'')
print name, connection_string, password
el archivo .properties
utilizado en mi ejemplo
name=mongo
connection-string=mongodb://...
password=my-password%1234
Editar 2015-11-06
Gracias a Neill Lima por mencionar que hubo un problema con el carácter %
.
El motivo de ello es que ConfigParser
está diseñado para analizar archivos .ini
. El carácter %
es una sintaxis especial. para usar el carácter %
simplemente agregue aa reemplazar por %
con %%
acuerdo con la sintaxis .ini
.
El módulo ConfigParser
genera una excepción si uno analiza un archivo .properties
estilo Java simple, cuyo contenido son pares clave-valor (es decir, sin encabezados de sección de estilo INI). ¿Hay alguna solución?
Digamos que tienes, por ejemplo:
$ cat my.props
first: primo
second: secondo
third: terzo
es decir, sería un formato .config
, excepto que falta un nombre de sección .config
. Entonces, es fácil falsificar el encabezado de la sección:
import ConfigParser
class FakeSecHead(object):
def __init__(self, fp):
self.fp = fp
self.sechead = ''[asection]/n''
def readline(self):
if self.sechead:
try:
return self.sechead
finally:
self.sechead = None
else:
return self.fp.readline()
uso:
cp = ConfigParser.SafeConfigParser()
cp.readfp(FakeSecHead(open(''my.props'')))
print cp.items(''asection'')
salida:
[(''second'', ''secondo''), (''third'', ''terzo''), (''first'', ''primo'')]
La respuesta anterior de Alex Martelli no funciona para Python 3.2+: readfp()
ha sido reemplazado por read_file()
, y ahora toma un iterador en lugar de usar el método readline()
.
Aquí hay un fragmento de código que utiliza el mismo enfoque, pero funciona en Python 3.2+.
>>> import configparser
>>> def add_section_header(properties_file, header_name):
... # configparser.ConfigParser requires at least one section header in a properties file.
... # Our properties file doesn''t have one, so add a header to it on the fly.
... yield ''[{}]/n''.format(header_name)
... for line in properties_file:
... yield line
...
>>> file = open(''my.props'', encoding="utf_8")
>>> config = configparser.ConfigParser()
>>> config.read_file(add_section_header(file, ''asection''), source=''my.props'')
>>> config[''asection''][''first'']
''primo''
>>> dict(config[''asection''])
{''second'': ''secondo'', ''third'': ''terzo'', ''first'': ''primo''}
>>>
Mi solución es usar StringIO
y StringIO
un simple encabezado ficticio:
import StringIO
import os
config = StringIO.StringIO()
config.write(''[dummysection]/n'')
config.write(open(''myrealconfig.ini'').read())
config.seek(0, os.SEEK_SET)
import ConfigParser
cp = ConfigParser.ConfigParser()
cp.readfp(config)
somevalue = cp.getint(''dummysection'', ''somevalue'')
Otra respuesta para python2.7 basada en la respuesta de Alex Martelli.
import ConfigParser
class PropertiesParser(object):
"""Parse a java like properties file
Parser wrapping around ConfigParser allowing reading of java like
properties file. Based on example:
https://.com/questions/2819696/parsing-properties-file-in-python/2819788#2819788
Example usage
-------------
>>> pp = PropertiesParser()
>>> props = pp.parse(''/home/kola/configfiles/dev/application.properties'')
>>> print props
"""
def __init__(self):
self.secheadname = ''fakeSectionHead''
self.sechead = ''['' + self.secheadname + '']/n''
def readline(self):
if self.sechead:
try:
return self.sechead
finally:
self.sechead = None
else:
return self.fp.readline()
def parse(self, filepath):
self.fp = open(filepath)
cp = ConfigParser.SafeConfigParser()
cp.readfp(self)
self.fp.close()
return cp.items(self.secheadname)
Pensé que el comentario "read_string" de MestreLion era agradable y simple y merecía un ejemplo.
Para Python 3.2+, puedes implementar la idea de la "sección ficticia" como esta:
with open(CONFIG_PATH, ''r'') as f:
config_string = ''[dummy_section]/n'' + f.read()
config = configparser.ConfigParser()
config.read_string(config_string)
Esta respuesta sugiere usar itertools.chain en Python 3.
from configparser import ConfigParser
from itertools import chain
parser = ConfigParser()
with open("foo.conf") as lines:
lines = chain(("[dummysection]",), lines) # This line does the trick.
parser.read_file(lines)
with open(''mykeyvaluepairs.properties'') as f:
defaults = dict([line.split() for line in f])
config = configparser.ConfigParser(defaults)
config.add_section(''dummy_section'')
Ahora config.get(''dummy_section'', option)
devolverá ''option'' de la sección DEFAULT.
o:
with open(''mykeyvaluepairs.properties'') as f:
properties = dict([line.split() for line in f])
config = configparser.ConfigParser()
config.add_section(''properties'')
for prop, val in properties.items():
config.set(''properties'', prop, val)
En cuyo caso config.get(''properties'', option)
no recurre a la sección predeterminada.
with open(''some.properties'') as file:
props = dict(line.strip().split(''='', 1) for line in file)
Crédito a Cómo crear un diccionario que contenga pares de valores clave de un archivo de texto
maxsplit=1
es importante si hay signos iguales en el valor (por ejemplo, someUrl=https://some.site.com/endpoint?id=some-value&someotherkey=value
)