File delle proprietà in Python (simile a Proprietà Java)


137

Dato il seguente formato ( .properties o .ini ):

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

Per Java esiste la classe Properties che offre funzionalità per analizzare / interagire con il formato sopra.

C'è qualcosa di simile in Python 's standard di biblioteca (2.x)?

In caso contrario, quali altre alternative ho?


5
Questa non è una domanda Java. Perché hai eseguito il rollback della rimozione dei tag Java?
BalusC,

Risposte:


69

Per i file .ini esiste il modulo ConfigParser che fornisce un formato compatibile con i file .ini.

Comunque non c'è niente disponibile per l'analisi di file .properties completi, quando devo farlo uso semplicemente jython (sto parlando di scripting).


10
pyjavaproperties sembra essere un'opzione se non si desidera utilizzare Jython: bitbucket.org/jnoller/pyjavaproperties
Hans-Christoph Steiner

2
il file delle proprietà java non è equivalente al file .ini. pyjavaproperties è la risposta giusta
igni

2
Alex Matelli suggerito un modo semplice per analizzare i file .properties con ConfigParser qui stackoverflow.com/a/2819788/15274
PI.

bitbucket.org/jnoller/pyjavaproperties non è stato mantenuto dal 2010. Non è compatibile con Python 3. Vorrei utilizzare le soluzioni collegate da @pi.
codyzu,

Dato che da nessuna parte qui è menzionato, vorrei aggiungere ancora che questo non è lo stesso. Non posso parlare per Java o Py3, e forse funziona con semplici valori / chiave. Ma la sintassi per l'interpolazione di stringhe è diversa. Questa soluzione fornisce la formattazione di Python, ad es. % (stringa) s while (ad esempio Ant) userò $ {string}. pymotw.com/2/ConfigParser
mpe

74

Sono stato in grado di farlo funzionare con ConfigParsernessuno, nessuno ha mostrato alcun esempio su come farlo, quindi ecco un semplice lettore Python di un file di proprietà ed esempio del file di proprietà. Nota che l'estensione è ancora .properties, ma ho dovuto aggiungere un'intestazione di sezione simile a quella che vedi nei file .ini ... un po 'di bastardizzazione, ma funziona.

Il file Python: PythonPropertyReader.py

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

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

Il file delle proprietà: ConfigFile.properties

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

Per ulteriori funzionalità, leggi: https://docs.python.org/2/library/configparser.html


5
Il modulo ConfigParser è stato rinominato configparser in Python 3.
Gursewak Singh,

Questo è per i file .ini, non per i file .properties poiché non contengono sezioni e configParser ha esito negativo se non trova alcuna intestazione di sezione. Inoltre, i file ini potrebbero non includere sezioni, quindi questo configParser non sembra affatto affidabile
BiAiB

65

Un file delle proprietà java è spesso anche un codice Python valido. È possibile rinominare il file myconfig.properties in myconfig.py. Quindi importa semplicemente il tuo file, in questo modo

import myconfig

e accedi direttamente alle proprietà

print myconfig.propertyName1

11
Mi piace l'idea, ma non funziona per le proprietà che contengono punti, prop.name="val"in questo caso non funzionerà.
maxjakob,

36
A java properties file is valid python code: Devo differire. Alcuni file delle proprietà Java passeranno per un codice Python valido, ma certamente non tutti. Come ha detto @mmjj i punti sono un problema. Quindi sono stringhe letterali non quotate. -1.
Manoj Govindan,

24
Un'idea piuttosto male ... dal momento che è rotto. I file di prop Java consentono ":" invece di "="; mangiano spazi bianchi dopo continuazioni di linea; non citano le stringhe. Niente di tutto ciò è "valido Python".
Dan H

2
In genere i file delle proprietà Java non passeranno per un codice Python valido. Un'alternativa è semplicemente impostare le proprietà in un file Python e utilizzare Python valido (ad esempio: MEDIA_ROOT = '/ foo') ...
danbgray

3
Questo è un hack da evitare. Avrai una brutta giornata quando cambierai le proprietà e il file non è più valido in Python.
r_2,

59

So che questa è una domanda molto vecchia, ma ne ho bisogno proprio ora e ho deciso di implementare la mia soluzione, una soluzione Python pura, che copre la maggior parte dei casi d'uso (non tutti):

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

È possibile modificare sepin ':' per analizzare i file con il formato:

key : value

Il codice analizza correttamente le righe come:

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

Otterrai un dict con:

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

1
Soluzione di prim'ordine ed è esattamente quello che stavo cercando!
Russell,

Nota che questo non supporta i commenti sulla stessa riga delle voci simili foo = "bar" # bat.
ThomasW

1
@ThomasW Se utilizziamo Java come standard di fatto, Proprietà # caricamento lo considererà come una proprietà foocon valore "bar" # bat.
bonh,

1
Hai pensato a cosa serve pubblicare una risposta a una vecchia domanda? Il punto è che sono stato in grado di risparmiare tempo semplicemente copiando e incollando questo, in una delle mie condotte azzurre piuttosto che implementarlo da solo. quindi grazie :)
vecchio monaco il

1
Adoro la risposta! L'unico cambiamento che ho fatto per gestire commenti in linea è stato quello di cambiare l = line.strip()per l = line.split(comment_char)[0].strip()e quindi verificare solo se lha un valore piuttosto sulla linea successiva con if l:.
Ben Dalling,

17

Se hai un'opzione di formati di file, ti suggerisco di usare .ini e Python's ConfigParser come menzionato. Se hai bisogno di compatibilità con i file .properties di Java, ho scritto una libreria per il suo nome jprops . Stavamo usando pyjavaproperties, ma dopo aver incontrato vari limiti ho finito per implementare il mio. Ha il pieno supporto per il formato .properties, incluso il supporto unicode e un migliore supporto per le sequenze di escape. Jprops può anche analizzare qualsiasi oggetto simile a un file mentre pyjavaproperties funziona solo con file reali su disco.


1
Ho appena provato questo. Funziona come un fascino. +1 per MattGood!
Dan H,

1
se aggiungi pip install e un esempio di codice, la tua risposta sarà ancora migliore pip install jprops, con open (percorso) come fp: properties = jprops.load_properties (fp) print (proprietà)
Rubber Duck

10

se non hai proprietà multi-linea e un bisogno molto semplice, alcune righe di codice possono risolverlo per te:

File t.properties:

a=b
c=d
e=f

Codice 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}



3

Questa è una sostituzione uno a uno di java.util.Propeties

Dal documento:

  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

È possibile utilizzare un oggetto simile a un file in ConfigParser.RawConfigParser.readfpdefinito qui -> https://docs.python.org/2/library/configparser.html#ConfigParser.RawConfigParser.readfp

Definire una classe che sovrascrive readlineche aggiunge un nome di sezione prima del contenuto effettivo del file delle proprietà.

L'ho impacchettato nella classe che restituisce una dictdi tutte le proprietà definite.

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

l'ho usato, questa libreria è molto 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

Questo è quello che sto facendo nel mio progetto: ho appena creato un altro file .py chiamato properties.py che include tutte le variabili / proprietà comuni che ho usato nel progetto, e in ogni file ho bisogno di fare riferimento a queste variabili, mettere

from properties import *(or anything you need)

Ho usato questo metodo per mantenere la pace di svn quando cambiavo spesso le posizioni degli sviluppatori e alcune variabili comuni erano abbastanza relative all'ambiente locale. Funziona bene per me, ma non sono sicuro che questo metodo sia suggerito per l'ambiente di sviluppo formale ecc.


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

Contenuti di test.json: {"host": "127.0.0.1", "user": "jms"}


2

Ho creato un modulo Python che è quasi simile alla classe Proprietà di Java (In realtà è come il PropertyPlaceholderConfigurer in primavera che ti permette di usare $ {variabile-riferimento} per fare riferimento alla proprietà già definita)

EDIT: È possibile installare questo pacchetto eseguendo il comando (attualmente testato per Python 3).
pip install property

Il progetto è ospitato su GitHub

Esempio: (la documentazione dettagliata è disponibile qui )

Supponiamo che tu abbia le seguenti proprietà definite nel file my_file.properties

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

Codice per caricare le proprietà sopra

from properties.p import Property

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

Supponiamo che tu abbia le seguenti proprietà definite nel file my_file.properties foo = I am awesome bar = $ {chocolate} -bar chocolate = fudge Codice per caricare le proprietà di cui sopra prop = Property () prop.load ('path / to / my_file .properties ') prop.get (' foo ') # I am awesome prop.get (' bar ') # fudge-bar
Anand Joshi,

Fatto . Spero che aiuti
Anand Joshi,

2

Se devi leggere tutti i valori da una sezione nel file delle proprietà in modo semplice:

Il tuo config.propertieslayout di file:

[SECTION_NAME]  
key1 = value1  
key2 = value2  

Si codice:

   import configparser

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

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

Questo ti darà un dizionario in cui le chiavi sono le stesse del file di configurazione e i loro valori corrispondenti.

details_dict è:

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

Ora per ottenere il valore di key1: details_dict['key1']

Mettendo tutto in un metodo che legge quella sezione dal file di configurazione una sola volta (la prima volta che il metodo viene chiamato durante l'esecuzione di un programma).

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

Ora chiama la funzione sopra e ottieni il valore della chiave richiesta:

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

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

Estendere l'approccio sopra menzionato, leggendo la sezione per sezione automaticamente e quindi accedendo per nome della sezione seguito dal nome della chiave.

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

Accedere:

config_dict = get_config_section()

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

(qui 'DB' è un nome di sezione nel file di configurazione e 'port' è una chiave nella sezione 'DB'.)


1

Sotto 2 righe di codice mostra come utilizzare Python List Comprehension per caricare il file delle proprietà 'java style'.

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

Si prega di dare un'occhiata al post qui sotto per i dettagli https://ilearnonlinesite.wordpress.com/2017/07/24/reading-property-file-in-python-using-comprehension-and-generators/


Il codice non chiude l'oggetto file, anche il collegamento solo la risposta non è gradita.
Aristotele,

Tale soluzione non copre valori multilinea o valori che includono un segno di uguale.
Konstantin Tarashchanskiy,

1

puoi usare il parametro "fromfile_prefix_chars" con argparse per leggere dal file di configurazione come sotto ---

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)

file di configurazione

--a
hello
--b
hello dear

Esegui comando

python temp.py "#config"

0

Ho fatto questo usando ConfigParser come segue. Il codice presuppone che esista un file chiamato config.prop nella stessa directory in cui si trova BaseTest:

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

Questo è ciò che avevo scritto per analizzare il file e impostarlo come variabili env che salta i commenti e le righe di valori non chiave hanno aggiunto opzioni per specificare hg: d

  • -h o --help riepiloga utilizzo stampa
  • -c Specifica il carattere che identifica il commento
  • -s Separatore tra chiave e valore nel file prop
  • e specifica il file delle proprietà che deve essere analizzato, ad esempio: 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 ha rilasciato la libreria Typesafe Config , che analizza i file delle proprietà e anche alcune estensioni basate su JSON. La libreria di Lightbend è solo per JVM, ma sembra essere ampiamente adottata e ora ci sono porte in molte lingue, incluso Python: https://github.com/chimpler/pyhocon


0

È possibile utilizzare la seguente funzione, che è il codice modificato di @mvallebr. Rispetta i commenti del file delle proprietà, ignora le nuove righe vuote e consente di recuperare un singolo valore chiave.

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

questo funziona per me.

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

Rimuovi questo post duplicato. tra l'altro ho votato l'altro;)
javadba il

0

Ho seguito l'approccio configparser e ha funzionato abbastanza bene per me. Creato un file PropertyReader e usato lì il parser di configurazione per la proprietà ready corrispondente a ciascuna sezione.

** Usato Python 2.7

Contenuto del file 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

Contenuto del file di schema letto:

from PropertyReader import *

class ReadSchema:

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

Contenuto del file .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

Questo è un file ini, il file delle proprietà non avrà intestazioni di sezione
Akshay

0

crea un dizionario nel tuo modulo Python e archivia tutto al suo interno e accedilo, ad esempio:

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

Ora per accedervi puoi semplicemente fare:

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

1
Si consiglia vivamente di condividere alcuni esempi di codice. Per ora la tua risposta è molto scarsa
Nikolai Shevchenko,

@NikolayShevchenko scusa per la formattazione scadente, ho aggiornato la mia risposta
Vineet Singh,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.