parsing.fichier de propriétés en Python

le module ConfigParser soulève une exception si l'on analyse un simple fichier de style Java .properties dont le contenu est composé de paires de valeurs clés (I..e sans en-têtes de section de style INI). Est-il une solution de contournement?

42
demandé sur Tshepang 2010-05-12 18:25:01

9 réponses

dire que vous avez, par exemple:

$ cat my.props
first: primo
second: secondo
third: terzo

, c'est-à-dire un format .config , sauf qu'il manque le nom d'une section principale. Ensuite, il est facile de simuler l'en-tête de section:

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()

utilisation:

cp = ConfigParser.SafeConfigParser()
cp.readfp(FakeSecHead(open('my.props')))
print cp.items('asection')

sortie:

[('second', 'secondo'), ('third', 'terzo'), ('first', 'primo')]
70
répondu Alex Martelli 2015-02-17 13:09:53

ma solution est d'utiliser StringIO et de préparer un simple en-tête de mannequin:

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')
31
répondu tauran 2013-12-09 20:38:25

j'ai pensé MestreLion "read_string" commentaire était beau et simple et mérite d'être un exemple.

pour Python 3.2+, vous pouvez implémenter l'idée de la" section mannequin "comme ceci:

with open(CONFIG_PATH, 'r') as f:
    config_string = '[dummy_section]\n' + f.read()
config = configparser.ConfigParser()
config.read_string(config_string)
26
répondu CoupleWavyLines 2017-05-23 10:31:29

la réponse d'Alex Martelli ci-dessus ne fonctionne pas pour Python 3.2+: readfp() a été remplacé par read_file() , et il faut maintenant un itérateur au lieu d'utiliser la méthode readline() .

voici un extrait qui utilise la même approche, mais fonctionne 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'}
>>>
16
répondu Oscar de Groot 2011-12-18 23:46:01

YAY! une autre version

basé sur cette réponse (l'ajout utilise un énoncé dict , with , et supporte le caractère % )

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'))

Utilisation

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

le .properties fichier utilisé dans mon exemple

name=mongo
connection-string=mongodb://...
password=my-password%1234

Modifier 2015-11-06

grâce à Neill Lima mentionnant qu'il y avait un problème avec le caractère % .

la raison en est ConfigParser conçu pour analyser .ini fichiers. Le caractère % est une syntaxe spéciale. afin d'utiliser le caractère % il a simplement ajouté un a remplacer pour % par %% selon la syntaxe .ini .

3
répondu Jossef Harush 2017-05-23 12:26:17
with open('some.properties') as file:
    props = dict(line.strip().split('=', 1) for line in file)

crédit à comment créer un dictionnaire qui contient des paires de valeurs clés à partir d'un fichier texte

maxsplit=1 est important s'il y a des signes égaux dans la valeur (par exemple someUrl=https://some.site.com/endpoint?id=some-value&someotherkey=value )

2
répondu user9192156 2018-08-19 04:53:06

Cette réponse suggère d'utiliser itertools.chaîne 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)
0
répondu Christian Long 2017-05-23 12:17:54
with open('mykeyvaluepairs.properties') as f:
    defaults = dict([line.split() for line in f])
config = configparser.ConfigParser(defaults)
config.add_section('dummy_section')

maintenant config.get('dummy_section', option) retournera "option" de la section par défaut.

ou:

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)

dans ce cas config.get('properties', option) n'a pas recours à la section par défaut.

-1
répondu Scruffy 2013-09-08 06:01:43

encore une autre réponse pour python2.7 basé sur réponse D'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 stackoverflow example:
    /q/parsing-properties-file-in-python-9858/"""

    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)
-1
répondu KolaB 2017-10-23 17:11:56