Файл властивостей у python (подібний до властивостей Java)


137

Дано наступний формат (. Властивості або .ini ):

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

Для Java існує клас Властивості, який пропонує функціональний аналіз для взаємодії з вищевказаним форматом.

Чи є що - щось подібне в Python «S стандартної бібліотеки (2.x)?

Якщо ні, то які інші альтернативи у мене є?


5
Це не питання Java. Чому ви відкатали видалення тегу Java?
BalusC

Відповіді:


69

Для файлів .ini існує модуль ConfigParser, який забезпечує формат, сумісний з файлами .ini.

У будь-якому разі немає нічого доступного для розбору повних файлів .properties, коли мені це потрібно зробити, я просто використовую jython (я говорю про сценарії).


10
pyjavaproperties здається варіантом, якщо ви не хочете використовувати Jython: bitbucket.org/jnoller/pyjavaproperties
Hans-Christoph Steiner

2
файл властивостей Java не еквівалентний .ini файлу. pyjavaproperties - правильна відповідь
igni

2
Алекс Мателл запропонував простий спосіб синтаксичного аналізу .properties файлів з ConfigParser тут stackoverflow.com/a/2819788/15274
пі.

bitbucket.org/jnoller/pyjavaproperties не підтримується з 2010 року. Він не сумісний з python 3. Я б використовував рішення, пов'язані з @pi.
codyzu

Оскільки ніде тут не згадується, дозволю ще раз додати, що це не те саме. Я не можу говорити на Java або Py3, і, можливо, це працює для простого ключа / значення. Але синтаксис для рядкової інтерполяції відрізняється. Це рішення забезпечує форматування Python, тобто. % (string) s, тоді як (наприклад, Ant) я б використовував $ {string}. pymotw.com/2/ConfigParser
mpe

74

Мені вдалося з цим попрацювати ConfigParser, ніхто не показав прикладів, як це зробити, тому ось простий зчитувач пітонів файлу властивостей та приклад файлу властивостей. Зауважте, що розширення все ще є .properties, але мені довелося додати заголовок розділу, схожий на те, що ви бачите у файлах .ini ... трохи бастардізація, але це працює.

Файл python: PythonPropertyReader.py

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

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

Файл властивості: ConfigFile.properties

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

Для отримання додаткових функцій читайте: https://docs.python.org/2/library/configparser.html


5
Модуль ConfigParser перейменовано на configparser в Python 3.
Gursewak Singh

Це для файлів .ini, а не для файлів .properties, оскільки вони не містять розділів, а configParser виходить з ладу, якщо в ньому не знайдено жодного заголовка розділу. Більше того, ini-файли можуть не включати розділи, тому цей configParser зовсім не здається надійним
BiAiB

65

Файл властивостей Java часто також є дійсним кодом python. Ви можете перейменувати файл myconfig.properties у myconfig.py. Потім просто імпортуйте файл, як це

import myconfig

і безпосередньо отримувати доступ до властивостей

print myconfig.propertyName1

11
Мені подобається ідея, але вона не працює для властивостей, які містять крапки, тобто prop.name="val"не збирається працювати в цьому випадку.
maxjakob

36
A java properties file is valid python code: Я повинен відрізнятися. Деякі файли властивостей Java передаватимуть дійсний код python, але, безумовно, не всі. Як @mmjj сказав, крапки є проблемою. Так є і без цитованих буквальних рядків. -1.
Маной Говіндан

24
Досить погана ідея ... оскільки вона порушена. Підтримуючі файли Java дозволяють ":" замість "="; вони їдять пробіл після продовження лінії; вони не цитують рядків. Нічого з цього не є "дійсним Python".
Dan H

2
Файли властивостей Java, як правило, не передаються для дійсного коду python. Одна з альтернатив - просто встановити свої властивості у файлі python та використовувати дійсний python (наприклад: MEDIA_ROOT = '/ foo') ...
danbgray

3
Цього зламу найкраще уникати. У тебе буде поганий день, коли ти зміниш властивості і файл не є дійсним python.
r_2

59

Я знаю, що це дуже давнє запитання, але воно мені зараз потрібне, і я вирішив реалізувати власне рішення, чисте рішення python, яке охоплює більшість випадків використання (не всіх):

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

Ви можете змінити sepна ":" для аналізу файлів у форматі:

key : value

Код правильно аналізує рядки, такі як:

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

Ви отримаєте диктант із:

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

1
Найкраще рішення та саме те, що я шукав!
Рассел

Зауважте, що це не підтримує коментарів у тому ж рядку, що і записи foo = "bar" # bat.
ThomasW

1
@ThomasW Якщо ми використовуємо Java як стандарт де-факто, завантаження Properties # розглядає це як властивість fooзі значенням "bar" # bat.
bonh

1
Ви думали, який сенс у розміщенні відповіді на старе запитання? Справа в тому, що я зміг заощадити час, просто скопіювавши це вставити в одному з моїх блакитних конвеєрів, а не реалізуючи його сам. тож дякую :)
старець-монах

1
Люблю відповідь! Єдина зміна , яке я зробив , щоб обробляти вбудовані коментарі було змінити , l = line.strip()щоб l = line.split(comment_char)[0].strip()потім тільки перевірити, lмає значення , а на наступній рядку з if l:.
Бен Даллінг

17

Якщо у вас є варіант форматів файлів, я пропоную використовувати .ini та Python's ConfigParser, як згадувалося. Якщо вам потрібна сумісність з файлами Java .properties, я написав бібліотеку для неї під назвою jprops . Ми використовували pyjavaproperties, але, зіткнувшись з різними обмеженнями, я в кінцевому підсумку реалізував власні. Він має повну підтримку формату .properties, включаючи підтримку unicode та кращу підтримку послідовностей евакуації. Jprops також може проаналізувати будь-який файл-подібний об'єкт, тоді як pyjavaproperties працює лише з реальними файлами на диску.


1
Я просто спробував це. Працює як шарм. +1 для MattGood!
Dan H

1
якщо ви додасте встановлення pip та приклад коду, вашою відповіддю буде ще краще встановити jprops з pip, з відкритим (шлях) як fp: Properties = jprops.load_properties (fp) print (властивості)
Rubber Duck

10

якщо у вас немає властивостей кількох рядків і дуже проста потреба, кілька рядків коду можуть вирішити це за вас:

Файл t.properties:

a=b
c=d
e=f

Код 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

Це не зовсім властивості, але Python має гарну бібліотеку для розбору конфігураційних файлів. Дивіться також цей рецепт: Заміна пітона для java.util.Properties .


1
За другим посиланням ... Це вже не активно розвивається. Джессі Ноллер створив проект з цього рецепту з деякими виправленнями, недоступними тут. Автор рекомендує цей проект усім, хто використовує цей рецепт. pypi.python.org/pypi/pyjavaproperties
Великий Аль


3

Це заміна один на один java.util.Propeties

Від док.

  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

Ви можете використовувати файл, схожий на ConfigParser.RawConfigParser.readfpвизначений тут об'єкт -> https://docs.python.org/2/library/configparser.html#ConfigParser.RawConfigParser.readfp

Визначте клас, який переосмислює readlineдодавання назви розділу перед фактичним вмістом вашого файла властивостей.

Я упакував його в клас, який повертає dictвсі визначені властивості.

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

я використав це, ця бібліотека дуже корисна

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

Це те, що я роблю в своєму проекті: я просто створюю інший .py файл під назвою Properties.py, який включає всі загальні змінні / властивості, які я використовував у проекті, і в будь-якому файлі потрібно посилатися на ці змінні,

from properties import *(or anything you need)

Використовував цей метод, щоб підтримувати мир у спокої, коли я часто міняв місце розташування розробників, а деякі загальні змінні були досить відносними до місцевого середовища. Для мене добре працює, але не впевнений, що цей метод буде запропонований для офіційного середовища розробників тощо.


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

Зміст test.json: {"host": "127.0.0.1", "user": "jms"}


2

Я створив модуль python, який майже схожий на клас властивостей Java (насправді він схожий на PropertyPlaceholderConfigurer навесні, що дозволяє використовувати $ {varia-reference} для посилання на вже визначене властивість)

EDIT: Ви можете встановити цей пакет, запустивши команду (зараз перевірена на python 3).
pip install property

Проект розміщений на GitHub

Приклад: (Детальну документацію можна знайти тут )

Скажімо, у вас є такі властивості, визначені у файлі my_file.properties

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

Код для завантаження вищевказаних властивостей

from properties.p import Property

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

Скажімо, у вас є такі властивості, визначені у файлі my_file.properties foo = Я дивовижний бар = $ {chocolate} -бар шоколад = fudge Код для завантаження вищевказаних властивостей prop = Properties () prop.load ('шлях / до / my_file .properties ') prop.get (' foo ') # Я дивовижний prop.get (' bar ') # fudge-bar
Anand Joshi

Зроблено. Сподіваюся, що це допомагає
Ананд Джоші

2

Якщо вам потрібно прочитати всі значення з розділу у файлі властивостей простим способом:

config.propertiesМакет вашого файлу:

[SECTION_NAME]  
key1 = value1  
key2 = value2  

Ви кодуєте:

   import configparser

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

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

Це дасть вам словник, де ключі такі ж, як у конфігураційному файлі та відповідні їм значення.

details_dict є:

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

Тепер, щоб отримати значення key1: details_dict['key1']

Поклавши все це у метод, який читає цей розділ з конфігураційного файлу лише один раз (перший раз, коли метод викликається під час виконання програми).

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

Тепер зателефонуйте до вищевказаної функції та отримайте необхідне значення ключа:

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

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

Розширюючи вищезазначений підхід, читайте розділ за розділом автоматично, а потім отримуйте доступ до назви розділу, а потім імені ключа.

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

Доступу:

config_dict = get_config_section()

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

(тут 'DB' - назва розділу у конфігураційному файлі, а 'port' - ключ у розділі 'DB'.)


1

Нижче у двох рядках коду показано, як використовувати Зрозуміння списку Python для завантаження файлу властивостей "java style".

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

Деталі https://ilearnonlinesite.wordpress.com/2017/07/24/reading-property-file-in-python-using-compression-and-generators/ дивіться нижче в розділі нижче.


Код не закриває об'єкт файлу, також лише відповідь не вітається.
aristotll

Це рішення не охоплює багаторядкові значення або значення, що містять знак рівності.
Костянтин Таращанський

1

ви можете використовувати параметр "fromfile_prefix_chars" з argparse для читання з конфігураційного файлу, як показано нижче ---

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)

конфігураційний файл

--a
hello
--b
hello dear

Виконати команду

python temp.py "#config"

0

Я зробив це за допомогою ConfigParser наступним чином. Код передбачає, що в тому самому каталозі, де розміщено BaseTest, є файл під назвою config.prop:

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

Це те, що я написав для розбору файлу і встановив його як змінну env, яка пропускає коментарі та не ключові рядки значення додає перемикачі, щоб вказати hg: d

  • -h або --допомога зведення використання друку
  • -c Вкажіть char, який ідентифікує коментар
  • -s Роздільник між ключем і значенням у проп-файлі
  • і вкажіть файл властивостей, який потрібно проаналізувати, наприклад: 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 випустив бібліотеку Typesafe Config , яка аналізує файли властивостей, а також деякі розширення на базі JSON. Бібліотека Lightbend призначена лише для JVM, але вона, здається, широко прийнята, і зараз є порти багатьма мовами, включаючи Python: https://github.com/chimpler/pyhocon


0

Ви можете використовувати таку функцію, яка є модифікованим кодом @mvallebr. Він поважає коментарі до файлів властивостей, ігнорує порожні нові рядки та дозволяє отримати значення одного ключа.

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

це працює для мене.

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

Видаліть цю копію публікації. btw Я порушив ваш інший;)
javadba

0

Я дотримувався підходу configparser, і він працював досить добре для мене. Створив один файл PropertyReader і використав там аналізатор конфігурації, щоб підготувати властивість до відповідного кожному розділу.

** Б / в Python 2.7

Вміст файлу 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

Вміст прочитаного файлу схеми:

from PropertyReader import *

class ReadSchema:

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

Вміст файлу .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

Це іні файл, властивості файлу не матиме заголовки розділів
Акшай

0

створити словник у вашому модулі python і зберегти все до нього та отримати доступ до нього, наприклад:

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

Тепер, щоб отримати доступ до нього, ви можете просто зробити:

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

1
Настійно рекомендується поділитися зразком коду. Наразі ваша відповідь дуже погана
Микола Шевченко

@NikolayShevchenko вибачте за неякісне форматування, я оновив свою відповідь
Vineet Singh
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.