Arquivo de propriedades em python (semelhante ao Java Properties)

137

Dado o seguinte formato ( .properties ou .ini ):

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

Para Java, há a classe Propriedades que oferece funcionalidade para analisar / interagir com o formato acima.

Existe algo semelhante em python é padrão biblioteca (2.x)?

Caso contrário, que outras alternativas eu tenho?

Andrei Ciobanu
fonte
5
Esta não é uma pergunta sobre Java. Por que você reverteu a remoção da tag Java?
precisa saber é o seguinte

Respostas:

69

Para arquivos .ini, existe o módulo ConfigParser que fornece um formato compatível com arquivos .ini.

De qualquer forma, não há nada disponível para analisar arquivos .properties completos, quando preciso fazer isso, simplesmente uso jython (estou falando sobre scripts).

pygabriel
fonte
10
pyjavaproperties parece ser uma opção se você não quiser usar Jython: bitbucket.org/jnoller/pyjavaproperties
Hans-Christoph Steiner
2
o arquivo de propriedades java não é equivalente ao arquivo .ini. pyjavaproperties é a resposta certa
igni
2
Alex Matelli sugeriu uma maneira fácil de analisar arquivos .properties com o ConfigParser aqui stackoverflow.com/a/2819788/15274
pi.
O bitbucket.org/jnoller/pyjavaproperties não é mantido desde 2010. Não é compatível com o python 3. Eu usaria as soluções vinculadas pelo @pi.
Codyzu
Como em nenhum lugar aqui é mencionado, deixe-me acrescentar novamente que isso não é o mesmo. Eu não posso falar por Java ou Py3, e talvez funcione para valores / chaves simples. Mas a sintaxe para interpolação de strings é diferente. Esta solução fornece formatação Python, ie. % (string) s while (por exemplo, Ant) eu usaria $ {string}. pymotw.com/2/ConfigParser
mpe
74

Consegui fazer isso funcionar ConfigParser, ninguém mostrou nenhum exemplo de como fazer isso, então aqui está um simples leitor python de um arquivo de propriedades e um exemplo do arquivo de propriedades. Observe que a extensão ainda está .properties, mas eu tive que adicionar um cabeçalho de seção semelhante ao que você vê nos arquivos .ini ... um pouco de bastardização, mas funciona.

O arquivo python: PythonPropertyReader.py

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

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

O arquivo de propriedades: ConfigFile.properties

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

Para obter mais funcionalidades, leia: https://docs.python.org/2/library/configparser.html

James Oravec
fonte
5
O módulo ConfigParser foi renomeado para ConfigParser em Python 3.
Gursewak Singh
Isso é para arquivos .ini, não arquivos .properties, pois eles não contêm seções, e o configParser falhará se não encontrar nenhum cabeçalho de seção. Além disso, os arquivos ini podem não incluir seções, portanto, este configParser não parece confiável
BiAiB
65

Um arquivo de propriedades java também é frequentemente um código python válido. Você pode renomear seu arquivo myconfig.properties para myconfig.py. Em seguida, basta importar seu arquivo, assim

import myconfig

e acesse as propriedades diretamente

print myconfig.propertyName1
Travis Bear
fonte
11
Gosto da ideia, mas ela não funciona para propriedades que contêm pontos, ou prop.name="val"seja, não vai funcionar nesse caso.
precisa saber é o seguinte
36
A java properties file is valid python code: Eu tenho que diferir. Alguns arquivos de propriedades Java passam por código python válido, mas certamente não todos. Como @mmjj disse que os pontos são um problema. O mesmo acontece com cadeias literais sem aspas. -1.
Manoj Govindan
24
Uma idéia bastante ruim ... já que está quebrada. Os arquivos prop Java permitem ":" em vez de "="; eles comem espaços em branco após continuações de linha; eles não citam seqüências de caracteres. Nada disso é "Python válido".
Dan H
2
Em geral, os arquivos de propriedades Java não passam por código python válido. Uma alternativa é apenas para definir suas propriedades em um arquivo de python e usar python válido (por exemplo: MEDIA_ROOT = '/ foo') ...
danbgray
3
É melhor evitar esse truque. Você terá um dia ruim quando alterar as propriedades e o arquivo não for mais um python válido.
r_2 30/05
59

Sei que essa é uma pergunta muito antiga, mas preciso dela agora e resolvi implementar minha própria solução, uma solução python pura, que cobre a maioria dos casos de uso (não todos):

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

Você pode alterar seppara ':' para analisar arquivos com o formato:

key : value

O código analisa corretamente as linhas como:

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

Você receberá um ditado com:

{"url": "http://my-host.com", "name": "Paul = Pablo" }
Roberto
fonte
1
Solução de primeira qualidade e é exatamente o que eu estava procurando!
Russell Russell
Observe que isso não suporta comentários na mesma linha que as entradas como foo = "bar" # bat.
precisa saber é o seguinte
1
@ThomasW Se estivermos usando Java como padrão de fato, o Properties # load tratará isso como uma propriedade foocom valor "bar" # bat.
Bonh 28/07/19
1
Você pensou qual é o sentido de postar resposta a uma pergunta antiga? O ponto é que eu pude economizar tempo, basta copiar e colar isso, em um dos meus pipeline do Azure, em vez de implementá-lo eu mesmo. então obrigado :)
old-monk
1
Ame a resposta! A única alteração que fiz para lidar com comentários embutidos foi mudar l = line.strip()para l = line.split(comment_char)[0].strip()e verificar apenas se ltem um valor na linha subsequente com if l:.
Ben Dalling
17

Se você tem uma opção de formatos de arquivo, sugiro usar o .ini e o ConfigParser do Python, conforme mencionado. Se você precisar de compatibilidade com arquivos Java .properties, escrevi uma biblioteca chamada jprops . Estávamos usando pyjavaproperties, mas depois de encontrar várias limitações, acabei implementando as minhas. Possui suporte completo para o formato .properties, incluindo suporte unicode e melhor suporte para seqüências de escape. O Jprops também pode analisar qualquer objeto semelhante a um arquivo, enquanto pyjavaproperties funciona apenas com arquivos reais no disco.

Matt Good
fonte
1
Eu apenas tentei. Funciona como um encanto. +1 para MattGood!
Dan H
1
se você adicionar pip instalar e um exemplo de código a sua resposta será ainda melhor pip instalar jprops, com open (caminho) como FP: Propriedades = jprops.load_properties (PF) de impressão (propriedades)
Rubber Duck
10

se você não possui propriedades de várias linhas e uma necessidade muito simples, algumas linhas de código podem resolver isso para você:

Arquivo t.properties:

a=b
c=d
e=f

Código 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}
mvallebr
fonte
4

Aqui está o link para o meu projeto: https://sourceforge.net/projects/pyproperties/ . É uma biblioteca com métodos para trabalhar com arquivos * .properties para o Python 3.x.

Mas não é baseado em java.util.Properties

marekjm
fonte
3

Esta é uma substituição individual do java.util.Propeties

Do 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.
tmow
fonte
3

Você pode usar um objeto semelhante a arquivo ConfigParser.RawConfigParser.readfpdefinido aqui -> https://docs.python.org/2/library/configparser.html#ConfigParser.RawConfigParser.readfp

Defina uma classe que substitui readlineque adiciona um nome de seção antes do conteúdo real do seu arquivo de propriedades.

Empacotei na classe que retorna uma dictde todas as propriedades definidas.

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()
Alexander Pogrebnyak
fonte
3

eu usei isso, essa biblioteca é muito útil

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'
Andy Quiroz
fonte
2

Isto é o que estou fazendo no meu projeto: eu apenas crio outro arquivo .py chamado properties.py que inclui todas as variáveis ​​/ propriedades comuns que usei no projeto e, em qualquer arquivo, é necessário referir-se a essas variáveis.

from properties import *(or anything you need)

Usei esse método para manter o svn em paz quando eu estava mudando os locais de desenvolvimento com frequência e algumas variáveis ​​comuns eram bastante relativas ao ambiente local. Funciona bem para mim, mas não tenho certeza se esse método seria sugerido para o ambiente formal de desenvolvimento, etc.

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

Conteúdo do test.json: {"host": "127.0.0.1", "usuário": "jms"}


fonte
2

Eu criei um módulo python que é quase semelhante à classe Properties do Java (na verdade, é como o PropertyPlaceholderConfigurer na primavera, que permite usar $ {variable-reference} para se referir à propriedade já definida)

EDIT: Você pode instalar este pacote executando o comando (atualmente testado para python 3).
pip install property

O projeto está hospedado no GitHub

Exemplo: (documentação detalhada pode ser encontrada aqui )

Digamos que você tenha as seguintes propriedades definidas no arquivo my_file.properties

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

Código para carregar as propriedades acima

from properties.p import Property

prop = Property()
# Simply load it into a dictionary
dic_prop = prop.load_property_files('my_file.properties')
Anand Joshi
fonte
Digamos que você tenha as seguintes propriedades definidas no arquivo my_file.properties foo = Eu sou incrível bar = $ {chocolate} -bar chocolate = fudge Código para carregar as propriedades acima prop = Property () prop.load ('path / to / my_file .properties ') prop.get (' foo ') # estou prop.get incrível (' bar ') # fudge-bar
Anand Joshi
Feito . Espero que ajude
Anand Joshi
2

Se você precisar ler todos os valores de uma seção no arquivo de propriedades de uma maneira simples:

O config.propertieslayout do seu arquivo:

[SECTION_NAME]  
key1 = value1  
key2 = value2  

Você codifica:

   import configparser

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

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

Isso fornecerá um dicionário onde as chaves são iguais às do arquivo de configuração e seus valores correspondentes.

details_dict é :

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

Agora, para obter o valor de key1: details_dict['key1']

Colocando tudo isso em um método que lê essa seção do arquivo de configuração apenas uma vez (na primeira vez em que o método é chamado durante a execução do programa).

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

Agora chame a função acima e obtenha o valor da chave necessária:

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

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

Estendendo a abordagem mencionada acima, lendo seção por seção automaticamente e acessando pelo nome da seção seguido pelo nome da chave.

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

Acessar:

config_dict = get_config_section()

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

(aqui 'DB' é um nome de seção no arquivo de configuração e 'port' é uma chave na seção 'DB'.)

TheCuriousOne
fonte
1

Abaixo, duas linhas de código mostram como usar o Python List Comprehension para carregar o arquivo de propriedades 'java style'.

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

Confira abaixo o post para obter detalhes https://ilearnonlinesite.wordpress.com/2017/07/24/reading-property-file-in-python-using-comprehension-and-generators/

Anoop Isaac
fonte
O código não fecha o objeto de arquivo, também a resposta apenas do link não é bem-vinda.
Aristotll
Essa solução não cobre valores de várias linhas ou valores que incluem um sinal de igual.
precisa saber é o seguinte
1

você pode usar o parâmetro "fromfile_prefix_chars" com argparse para ler o arquivo de configuração como abaixo ---

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)

arquivo de configuração

--a
hello
--b
hello dear

Comando de execução

python temp.py "#config"
Agrim Bansal
fonte
0

Eu fiz isso usando o ConfigParser da seguinte maneira. O código supõe que exista um arquivo chamado config.prop no mesmo diretório em que o BaseTest é colocado:

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
narko
fonte
0

Isto é o que eu escrevi para analisar o arquivo e defini-lo como variáveis ​​env, que ignora comentários e linhas de valor que não são chaves adicionadas para especificar hg: d

  • -h ou --help resumo do uso da impressão
  • -c Especifique o caractere que identifica o comentário
  • -s Separador entre chave e valor no arquivo prop
  • e especifique o arquivo de propriedades que precisa ser analisado, por exemplo: 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:])
patel
fonte
0

O Lightbend lançou a biblioteca Typesafe Config , que analisa arquivos de propriedades e também algumas extensões baseadas em JSON. A biblioteca do Lightbend é apenas para a JVM, mas parece ser amplamente adotada e agora existem portas em vários idiomas, incluindo Python: https://github.com/chimpler/pyhocon

DGrady
fonte
0

Você pode usar a seguinte função, que é o código modificado de @mvallebr. Ele respeita os comentários do arquivo de propriedades, ignora novas linhas vazias e permite recuperar um único valor de chave.

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
Memin
fonte
0

isso funciona para mim.

from pyjavaproperties import Properties
p = Properties()
p.load(open('test.properties'))
p.list()
print p
print p.items()
print p['name3']
Andy Quiroz
fonte
Remova esta postagem duplicada. btw eu
voto a favor do
0

Eu segui a abordagem do configparser e funcionou muito bem para mim. Criou um arquivo PropertyReader e usou o analisador de configuração para preparar a propriedade correspondente a cada seção.

** Usado Python 2.7

Conteúdo do arquivo 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

Conteúdo do arquivo de esquema de leitura:

from PropertyReader import *

class ReadSchema:

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

Conteúdo do arquivo .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
Vaibhav Shukla
fonte
Este é um arquivo ini, arquivo de propriedades não terá nenhum cabeçalhos de seção
Akshay
0

crie um dicionário no seu módulo python e armazene tudo nele e acesse-o, por exemplo:

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

Agora, para acessá-lo, você pode simplesmente:

submitButton = driver.find_element_by_id(dict['elementID'])
Vineet Singh
fonte
1
É altamente recomendável compartilhar alguns exemplos de código. Por enquanto, sua resposta é muito ruim #
Nikolai Shevchenko
@NikolayShevchenko pena de má formatação, eu atualizei a minha resposta
Vineet Singh