Fichier de propriétés en python (similaire aux propriétés Java)


137

Compte tenu du format suivant ( .properties ou .ini ):

propertyName1=propertyValue1
propertyName2=propertyValue2
...
propertyNameN=propertyValueN

Pour Java, il existe la classe Properties qui offre des fonctionnalités pour analyser / interagir avec le format ci-dessus.

Y a-t-il quelque chose de similaire dans la bibliothèque standard de python (2.x)?

Sinon, quelles autres alternatives ai-je?


5
Ce n'est pas une question Java. Pourquoi avez-vous annulé la suppression de la balise Java?
BalusC

Réponses:


69

Pour les fichiers .ini, il existe le module ConfigParser qui fournit un format compatible avec les fichiers .ini.

Quoi qu'il en soit, il n'y a rien de disponible pour analyser des fichiers .properties complets, quand je dois le faire, j'utilise simplement jython (je parle de script).


10
pyjavaproperties semble être une option si vous ne voulez pas utiliser Jython: bitbucket.org/jnoller/pyjavaproperties
Hans-Christoph Steiner

2
le fichier de propriétés java n'est pas équivalent au fichier .ini. pyjavaproperties est la bonne réponse
igni

2
Alex Matelli a suggéré un moyen simple d'analyser les fichiers .properties avec ConfigParser ici stackoverflow.com/a/2819788/15274
pi.

bitbucket.org/jnoller/pyjavaproperties n'a pas été maintenu depuis 2010. Il n'est pas compatible avec python 3. J'utiliserais les solutions liées par @pi.
codyzu le

Puisque nulle part ici il n'est mentionné, permettez-moi d'ajouter à nouveau que ce n'est pas la même chose. Je ne peux pas parler pour Java ou Py3, et peut-être que cela fonctionne pour des clés / valeurs simples. Mais la syntaxe de l'interpolation de chaîne est différente. Cette solution fournit le formatage Python, c'est à dire. % (string) s while (par exemple Ant) j'utiliserais $ {string}. pymotw.com/2/ConfigParser
mpe

74

J'ai pu faire fonctionner cela ConfigParser, personne n'a montré d'exemples sur la façon de le faire, voici donc un simple lecteur python d'un fichier de propriétés et un exemple du fichier de propriétés. Notez que l'extension est toujours .properties, mais j'ai dû ajouter un en-tête de section similaire à ce que vous voyez dans les fichiers .ini ... un peu une bâtardise, mais cela fonctionne.

Le fichier python: PythonPropertyReader.py

#!/usr/bin/python    
import ConfigParser
config = ConfigParser.RawConfigParser()
config.read('ConfigFile.properties')

print config.get('DatabaseSection', 'database.dbname');

Le fichier de propriété: ConfigFile.properties

[DatabaseSection]
database.dbname=unitTest
database.user=root
database.password=

Pour plus de fonctionnalités, lisez: https://docs.python.org/2/library/configparser.html


5
Le module ConfigParser a été renommé en configparser en Python 3.
Gursewak Singh

Ceci est pour les fichiers .ini, pas pour les fichiers .properties car ils ne contiennent pas de sections, et configParser échoue s'il ne trouve aucun en-tête de section. De plus, les fichiers ini peuvent ne pas inclure de sections, donc ce configParser ne semble pas du tout fiable
BiAiB

65

Un fichier de propriétés Java est souvent également du code Python valide. Vous pouvez renommer votre fichier myconfig.properties en myconfig.py. Ensuite, importez simplement votre fichier, comme ceci

import myconfig

et accédez directement aux propriétés

print myconfig.propertyName1

11
J'aime l'idée, mais cela ne fonctionne pas pour les propriétés qui contiennent des points, c'est prop.name="val"-à- dire ne fonctionnera pas dans ce cas.
maxjakob

36
A java properties file is valid python code: Je dois différer. Certains fichiers de propriétés Java passeront pour du code python valide, mais certainement pas tous. Comme @mmjj l'a dit, les points sont un problème. Il en va de même pour les chaînes littérales sans guillemets. -1.
Manoj Govindan

24
Une idée plutôt mauvaise ... car elle est cassée. Les fichiers prop Java autorisent ":" au lieu de "="; ils mangent des espaces après les continuations de ligne; ils ne citent pas de chaînes. Rien de tout cela n'est "Python valide".
Dan H

2
Les fichiers de propriétés Java ne sont généralement pas transmis pour un code Python valide. Une alternative consiste simplement à définir vos propriétés dans un fichier python et à utiliser un python valide (par exemple: MEDIA_ROOT = '/ foo') ...
danbgray

3
C'est un hack qu'il vaut mieux éviter. Vous allez avoir une mauvaise journée lorsque vos propriétés changent et que le fichier n'est plus valide en python.
r_2

59

Je sais que c'est une question très ancienne, mais j'en ai besoin tout à l'heure et j'ai décidé d'implémenter ma propre solution, une solution pure python, qui couvre la plupart des cas d'utilisation (pas tous):

def load_properties(filepath, sep='=', comment_char='#'):
    """
    Read the file passed as parameter as a properties file.
    """
    props = {}
    with open(filepath, "rt") as f:
        for line in f:
            l = line.strip()
            if l and not l.startswith(comment_char):
                key_value = l.split(sep)
                key = key_value[0].strip()
                value = sep.join(key_value[1:]).strip().strip('"') 
                props[key] = value 
    return props

Vous pouvez changer le sepen «:» pour analyser les fichiers au format:

key : value

Le code analyse correctement les lignes comme:

url = "http://my-host.com"
name = Paul = Pablo
# This comment line will be ignored

Vous obtiendrez un dict avec:

{"url": "http://my-host.com", "name": "Paul = Pablo" }

1
Solution de premier ordre et c'est exactement ce que je recherchais!
Russell

Notez que cela ne prend pas en charge les commentaires sur la même ligne que les entrées comme foo = "bar" # bat.
ThomasW

1
@ThomasW Si nous utilisons Java comme standard de facto, Properties # load traitera cela comme une propriété fooavec une valeur "bar" # bat.
bonh

1
Vous avez pensé à quoi bon poster une réponse à une vieille question? Le fait est que j'ai pu gagner du temps en copiant simplement ceci, dans l'un de mes pipelines Azure plutôt que de l'implémenter moi-même. alors merci :)
old-monk

1
J'adore la réponse! Le seul changement que je fait pour traiter les observations inline était de changer l = line.strip()pour l = line.split(comment_char)[0].strip()et seulement vérifier si lune valeur plutôt sur la ligne suivante avec if l:.
Ben Dalling le

17

Si vous avez une option de formats de fichiers, je suggère d'utiliser .ini et ConfigParser de Python comme mentionné. Si vous avez besoin de compatibilité avec les fichiers Java .properties, j'ai écrit une bibliothèque appelée jprops . Nous utilisions pyjavaproperties, mais après avoir rencontré diverses limitations, j'ai fini par implémenter les miennes. Il prend entièrement en charge le format .properties, y compris le support Unicode et une meilleure prise en charge des séquences d'échappement. Jprops peut également analyser n'importe quel objet de type fichier tandis que pyjavaproperties ne fonctionne qu'avec de vrais fichiers sur le disque.


1
Je viens de faire un essai. Fonctionne comme un charme. +1 pour MattGood!
Dan H

1
si vous ajoutez pip install et un exemple de code, votre réponse sera encore meilleure pip install jprops, avec open (path) as fp: properties = jprops.load_properties (fp) print (properties)
Rubber Duck

10

si vous n'avez pas de propriétés multi-lignes et un besoin très simple, quelques lignes de code peuvent le résoudre pour vous:

Fichier t.properties:

a=b
c=d
e=f

Code Python:

with open("t.properties") as f:
    l = [line.split("=") for line in f.readlines()]
    d = {key.strip(): value.strip() for key, value in l}

6

Ce ne sont pas exactement des propriétés mais Python a une belle bibliothèque pour analyser les fichiers de configuration. Voir aussi cette recette: Un remplacement python pour java.util.Properties .


1
Pour le deuxième lien ... Ce n'est plus développé activement. Jesse noller a créé un projet à partir de cette recette avec quelques correctifs non disponibles ici. L'auteur recommande ce projet à toute personne utilisant cette recette. pypi.python.org/pypi/pyjavaproperties
Big Al


3

Ceci est un remplacement un-à-un de java.util.

Du doc:

  def __parse(self, lines):
        """ Parse a list of lines and create
        an internal property dictionary """

        # Every line in the file must consist of either a comment
        # or a key-value pair. A key-value pair is a line consisting
        # of a key which is a combination of non-white space characters
        # The separator character between key-value pairs is a '=',
        # ':' or a whitespace character not including the newline.
        # If the '=' or ':' characters are found, in the line, even
        # keys containing whitespace chars are allowed.

        # A line with only a key according to the rules above is also
        # fine. In such case, the value is considered as the empty string.
        # In order to include characters '=' or ':' in a key or value,
        # they have to be properly escaped using the backslash character.

        # Some examples of valid key-value pairs:
        #
        # key     value
        # key=value
        # key:value
        # key     value1,value2,value3
        # key     value1,value2,value3 \
        #         value4, value5
        # key
        # This key= this value
        # key = value1 value2 value3

        # Any line that starts with a '#' is considerered a comment
        # and skipped. Also any trailing or preceding whitespaces
        # are removed from the key/value.

        # This is a line parser. It parses the
        # contents like by line.

3

Vous pouvez utiliser un objet semblable à un fichier ConfigParser.RawConfigParser.readfpdéfini ici -> https://docs.python.org/2/library/configparser.html#ConfigParser.RawConfigParser.readfp

Définissez une classe qui remplace readlineet ajoute un nom de section avant le contenu réel de votre fichier de propriétés.

Je l'ai empaqueté dans la classe qui renvoie une dictde toutes les propriétés définies.

import ConfigParser

class PropertiesReader(object):

    def __init__(self, properties_file_name):
        self.name = properties_file_name
        self.main_section = 'main'

        # Add dummy section on top
        self.lines = [ '[%s]\n' % self.main_section ]

        with open(properties_file_name) as f:
            self.lines.extend(f.readlines())

        # This makes sure that iterator in readfp stops
        self.lines.append('')

    def readline(self):
        return self.lines.pop(0)

    def read_properties(self):
        config = ConfigParser.RawConfigParser()

        # Without next line the property names will be lowercased
        config.optionxform = str

        config.readfp(self)
        return dict(config.items(self.main_section))

if __name__ == '__main__':
    print PropertiesReader('/path/to/file.properties').read_properties()

3

j'ai utilisé ceci, cette bibliothèque est très utile

from pyjavaproperties import Properties
p = Properties()
p.load(open('test.properties'))
p.list()
print(p)
print(p.items())
print(p['name3'])
p['name3'] = 'changed = value'

2

C'est ce que je fais dans mon projet: je crée juste un autre fichier .py appelé properties.py qui comprend toutes les variables / propriétés courantes que j'ai utilisées dans le projet, et dans tout fichier, je dois faire référence à ces variables, mettez

from properties import *(or anything you need)

J'ai utilisé cette méthode pour garder svn la paix lorsque je changeais fréquemment les emplacements de développement et que certaines variables communes étaient assez relatives à l'environnement local. Fonctionne bien pour moi mais je ne suis pas sûr que cette méthode soit suggérée pour un environnement de développement formel, etc.


2
import json
f=open('test.json')
x=json.load(f)
f.close()
print(x)

Contenu de test.json: {"host": "127.0.0.1", "user": "jms"}


2

J'ai créé un module python qui est presque similaire à la classe Properties de Java (en fait, c'est comme le PropertyPlaceholderConfigurer au printemps qui vous permet d'utiliser $ {variable-reference} pour faire référence à une propriété déjà définie)

EDIT: Vous pouvez installer ce package en exécutant la commande (actuellement testée pour python 3).
pip install property

Le projet est hébergé sur GitHub

Exemple: (Une documentation détaillée peut être trouvée ici )

Supposons que vous ayez les propriétés suivantes définies dans le fichier my_file.properties

foo = I am awesome
bar = ${chocolate}-bar
chocolate = fudge

Code pour charger les propriétés ci-dessus

from properties.p import Property

prop = Property()
# Simply load it into a dictionary
dic_prop = prop.load_property_files('my_file.properties')

Supposons que vous ayez les propriétés suivantes définies dans le fichier my_file.properties foo = I am awesome bar = $ {chocolate} -bar chocolate = fudge Code pour charger les propriétés ci-dessus prop = Property () prop.load ('path / to / my_file .properties ') prop.get (' foo ') # Je suis génial prop.get (' bar ') # fudge-bar
Anand Joshi

Terminé . J'espère que ça aide
Anand Joshi

2

Si vous avez besoin de lire toutes les valeurs d'une section dans le fichier de propriétés d'une manière simple:

La config.propertiesmise en page de votre fichier:

[SECTION_NAME]  
key1 = value1  
key2 = value2  

Vous codez:

   import configparser

   config = configparser.RawConfigParser()
   config.read('path_to_config.properties file')

   details_dict = dict(config.items('SECTION_NAME'))

Cela vous donnera un dictionnaire où les clés sont les mêmes que dans le fichier de configuration et leurs valeurs correspondantes.

details_dict est :

{'key1':'value1', 'key2':'value2'}

Maintenant, pour obtenir la valeur de key1: details_dict['key1']

Mettre le tout dans une méthode qui lit cette section à partir du fichier de configuration une seule fois (la première fois que la méthode est appelée pendant l'exécution d'un programme).

def get_config_dict():
    if not hasattr(get_config_dict, 'config_dict'):
        get_config_dict.config_dict = dict(config.items('SECTION_NAME'))
    return get_config_dict.config_dict

Appelez maintenant la fonction ci-dessus et obtenez la valeur de la clé requise:

config_details = get_config_dict()
key_1_value = config_details['key1'] 

-------------------------------------------------- -----------

Extension de l'approche mentionnée ci-dessus, lecture section par section automatiquement puis accès par nom de section suivi du nom de clé.

def get_config_section():
    if not hasattr(get_config_section, 'section_dict'):
        get_config_section.section_dict = dict()

        for section in config.sections():
            get_config_section.section_dict[section] = 
                             dict(config.items(section))

    return get_config_section.section_dict

Accéder:

config_dict = get_config_section()

port = config_dict['DB']['port'] 

(ici 'DB' est un nom de section dans le fichier de configuration et 'port' est une clé sous la section 'DB'.)


1

Ci-dessous 2 lignes de code montre comment utiliser Python List Comprehension pour charger le fichier de propriétés 'java style'.

split_properties=[line.split("=") for line in open('/<path_to_property_file>)]
properties={key: value for key,value in split_properties }

Veuillez consulter l'article ci-dessous pour plus de détails https://ilearnonlinesite.wordpress.com/2017/07/24/reading-property-file-in-python-using-comprehension-and-generators/


Le code ne ferme pas l'objet fichier, la réponse de lien uniquement n'est pas la bienvenue.
aristotll

Cette solution ne couvre pas les valeurs multilignes ou les valeurs qui incluent un signe égal.
Konstantin Tarashchanskiy

1

vous pouvez utiliser le paramètre "fromfile_prefix_chars" avec argparse pour lire à partir du fichier de configuration comme ci-dessous ---

temp.py

parser = argparse.ArgumentParser(fromfile_prefix_chars='#')
parser.add_argument('--a')
parser.add_argument('--b')
args = parser.parse_args()
print(args.a)
print(args.b)

fichier de configuration

--a
hello
--b
hello dear

Exécuter la commande

python temp.py "#config"

0

J'ai fait cela en utilisant ConfigParser comme suit. Le code suppose qu'il existe un fichier appelé config.prop dans le même répertoire où BaseTest est placé:

config.prop

[CredentialSection]
app.name=MyAppName

BaseTest.py:

import unittest
import ConfigParser

class BaseTest(unittest.TestCase):
    def setUp(self):
        __SECTION = 'CredentialSection'
        config = ConfigParser.ConfigParser()
        config.readfp(open('config.prop'))
        self.__app_name = config.get(__SECTION, 'app.name')

    def test1(self):
        print self.__app_name % This should print: MyAppName

0

C'est ce que j'avais écrit pour analyser le fichier et le définir comme des variables d'environnement qui ignorent les commentaires et les lignes de valeur non clés ajoutées des commutateurs pour spécifier hg: d

  • -h ou --help affiche le résumé de l'utilisation
  • -c Spécifie le caractère qui identifie le commentaire
  • -s Séparateur entre la clé et la valeur dans le fichier prop
  • et spécifiez le fichier de propriétés qui doit être analysé, par exemple: python EnvParamSet.py -c # -s = env.properties

    import pipes
    import sys , getopt
    import os.path
    
    class Parsing :
    
            def __init__(self , seprator , commentChar , propFile):
            self.seprator = seprator
            self.commentChar = commentChar
            self.propFile  = propFile
    
        def  parseProp(self):
            prop = open(self.propFile,'rU')
            for line in prop :
                if line.startswith(self.commentChar)==False and  line.find(self.seprator) != -1  :
                    keyValue = line.split(self.seprator)
                    key =  keyValue[0].strip() 
                    value = keyValue[1].strip() 
                            print("export  %s=%s" % (str (key),pipes.quote(str(value))))
    
    
    
    
    class EnvParamSet:
    
        def main (argv):
    
            seprator = '='
            comment =  '#'
    
            if len(argv)  is 0:
                print "Please Specify properties file to be parsed "
                sys.exit()
            propFile=argv[-1] 
    
    
            try :
                opts, args = getopt.getopt(argv, "hs:c:f:", ["help", "seprator=","comment=", "file="])
            except getopt.GetoptError,e:
                print str(e)
                print " possible  arguments  -s <key value sperator > -c < comment char >    <file> \n  Try -h or --help "
                sys.exit(2)
    
    
            if os.path.isfile(args[0])==False:
                print "File doesnt exist "
                sys.exit()
    
    
            for opt , arg  in opts :
                if opt in ("-h" , "--help"):
                    print " hg:d  \n -h or --help print usage summary \n -c Specify char that idetifes comment  \n -s Sperator between key and value in prop file \n  specify file  "
                    sys.exit()
                elif opt in ("-s" , "--seprator"):
                    seprator = arg 
                elif opt in ("-c"  , "--comment"):
                    comment  = arg
    
            p = Parsing( seprator, comment , propFile)
            p.parseProp()
    
        if __name__ == "__main__":
                main(sys.argv[1:])

0

Lightbend a publié la bibliothèque Typesafe Config , qui analyse les fichiers de propriétés ainsi que certaines extensions basées sur JSON. La bibliothèque de Lightbend est uniquement destinée à la JVM, mais elle semble être largement adoptée et il existe désormais des ports dans de nombreux langages, y compris Python: https://github.com/chimpler/pyhocon


0

Vous pouvez utiliser la fonction suivante, qui est le code modifié de @mvallebr. Il respecte les commentaires du fichier de propriétés, ignore les nouvelles lignes vides et permet de récupérer une seule valeur de clé.

def getProperties(propertiesFile ="/home/memin/.config/customMemin/conf.properties", key=''):
    """
    Reads a .properties file and returns the key value pairs as dictionary.
    if key value is specified, then it will return its value alone.
    """
    with open(propertiesFile) as f:
        l = [line.strip().split("=") for line in f.readlines() if not line.startswith('#') and line.strip()]
        d = {key.strip(): value.strip() for key, value in l}

        if key:
            return d[key]
        else:
            return d

0

cela fonctionne pour moi.

from pyjavaproperties import Properties
p = Properties()
p.load(open('test.properties'))
p.list()
print p
print p.items()
print p['name3']

Veuillez supprimer cette publication en double. btw j'ai voté pour votre autre;)
javadba

0

J'ai suivi l'approche du configparser et cela a très bien fonctionné pour moi. Créé un fichier PropertyReader et utilisé l'analyseur de configuration pour préparer la propriété à correspondre à chaque section.

** Python 2.7 utilisé

Contenu du fichier PropertyReader.py:

#!/usr/bin/python
import ConfigParser

class PropertyReader:

def readProperty(self, strSection, strKey):
    config = ConfigParser.RawConfigParser()
    config.read('ConfigFile.properties')
    strValue = config.get(strSection,strKey);
    print "Value captured for "+strKey+" :"+strValue
    return strValue

Contenu du fichier de schéma lu:

from PropertyReader import *

class ReadSchema:

print PropertyReader().readProperty('source1_section','source_name1')
print PropertyReader().readProperty('source2_section','sn2_sc1_tb')

Contenu du fichier .properties:

[source1_section]
source_name1:module1
sn1_schema:schema1,schema2,schema3
sn1_sc1_tb:employee,department,location
sn1_sc2_tb:student,college,country

[source2_section]
source_name1:module2
sn2_schema:schema4,schema5,schema6
sn2_sc1_tb:employee,department,location
sn2_sc2_tb:student,college,country

Ceci est un fichier ini, le fichier de propriétés n'aura pas d'en-tête de section
Akshay

0

créez un dictionnaire dans votre module python et stockez-y tout et accédez-y, par exemple:

dict = {
       'portalPath' : 'www.xyx.com',
       'elementID': 'submit'}

Maintenant, pour y accéder, vous pouvez simplement faire:

submitButton = driver.find_element_by_id(dict['elementID'])

1
Il est fortement recommandé de partager un échantillon de code. Pour l'instant, votre réponse est très pauvre
Nikolai Shevchenko

@NikolayShevchenko désolé pour une mauvaise mise en forme, j'ai mis à jour ma réponse
Vineet Singh
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.