Файл свойств в Python (похож на свойства Java)

137

Учитывая следующий формат ( .properties или .ini ):

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

Для Java существует класс Properties, который предлагает функциональность для анализа / взаимодействия с вышеуказанным форматом.

Есть ли что - то подобное в Python «S стандартной библиотеки (2.x)?

Если нет, какие у меня есть альтернативы?

Андрей Чобану
источник
5
Это не вопрос Java. Почему вы откатили удаление тега Java?
BalusC

Ответы:

69

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

В любом случае, нет ничего доступного для разбора полных файлов .properties, когда я должен это сделать, я просто использую jython (я говорю о скриптах).

pygabriel
источник
10
Pyjavaproperties, кажется, вариант, если вы не хотите использовать Jython: bitbucket.org/jnoller/pyjavaproperties
Hans-Christoph Steiner
2
файл свойств Java не эквивалентен файлу .ini. pyjavaproperties - правильный ответ
igni
2
Алекс Мателли предложил простой способ анализа файлов .properties с ConfigParser здесь stackoverflow.com/a/2819788/15274
pi.
bitbucket.org/jnoller/pyjavaproperties не поддерживается с 2010 года. Он не совместим с python 3. Я бы использовал решения, связанные с @pi.
codyzu
Поскольку нигде здесь не упоминается, позвольте мне еще раз добавить, что это не то же самое. Я не могу говорить за Java или Py3, и, возможно, это работает для простых ключей / значений. Но синтаксис для интерполяции строк отличается. Это решение обеспечивает форматирование Python, т.е. % (string) s while (например, для Ant) я бы использовал $ {string}. pymotw.com/2/ConfigParser
mpe
74

Мне удалось заставить это работать ConfigParser, никто не показал никаких примеров того, как это сделать, так что вот простой python-ридер файла свойств и пример файла свойств. Обратите внимание, что расширение все еще есть .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».
Дэн Х
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 # load будет воспринимать это как свойство fooсо значением "bar" # bat.
Бон
1
Вы думали, что смысл публиковать ответ на старый вопрос? Дело в том, что я смог сэкономить время, просто скопировав и вставив это в один из моих лазурных конвейеров, а не реализовав его сам. так что спасибо :)
старый монах
1
Люблю ответ! Единственное изменение, которое я сделал для обработки встроенных комментариев, - это изменить l = line.strip()его, l = line.split(comment_char)[0].strip()а затем только проверять, lимеет ли значение значение в следующей строке с if l:.
Бен Даллинг
17

Если у вас есть возможность форматов файлов, я предлагаю использовать .ini и Python ConfigParser, как уже упоминалось. Если вам нужна совместимость с файлами Java .properties, я написал для нее библиотеку jprops . Мы использовали pyjavaproperties, но, столкнувшись с различными ограничениями, я реализовал свои собственные. Он имеет полную поддержку формата .properties, включая поддержку юникода и лучшую поддержку escape-последовательностей. Jprops также может анализировать любой файлоподобный объект, тогда как pyjavaproperties работает только с реальными файлами на диске.

Мэтт Гуд
источник
1
Я только что попробовал. Работает как шарм. +1 за MattGood!
Дэн Х
1
если вы добавите pip install и пример кода, ваш ответ будет еще лучше pip install jprops с open (path) в виде fp: properties = jprops.load_properties (fp) print (properties)
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}
mvallebr
источник
6

Это не совсем свойства, но в Python есть хорошая библиотека для разбора файлов конфигурации. Также посмотрите этот рецепт: замена 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.
tmow
источник
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)

Использовал этот метод, чтобы сохранить svn-мир, когда я часто менял расположение разработчиков, и некоторые общие переменные были довольно относительны к локальной среде. Хорошо работает для меня, но не уверен, что этот метод будет предложен для формальной среды разработки и т. Д.

festony
источник
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 весной, который позволяет вам использовать $ {variable-reference} для ссылки на уже определенное свойство)

РЕДАКТИРОВАТЬ: Вы можете установить этот пакет, выполнив команду (в настоящее время тестируется для 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 = Я удивительный bar = $ {chocolate} -bar chocolate = fudge Код для загрузки вышеуказанных свойств prop = Property () prop.load ('path / to / my_file) .properties ') prop.get (' foo ') # Я потрясающий prop.get (' bar ') # fudge-bar
Ананд Джоши
Готово . Надеюсь, это поможет
Ананд Джоши
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».)

TheCuriousOne
источник
1

В двух строках кода показано, как использовать Python List Conceptionsion для загрузки файла свойств '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-comprehension-and-generators/

Anoop Исаак
источник
Код не закрывает объект файла, также ответ только по ссылке не приветствуется.
Аристотель
Это решение не распространяется на многострочные значения или значения, содержащие знак равенства.
Константин Таращанский
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
Narko
источник
0

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

  • -h или --help сводка использования печати
  • -c Укажите символ, который идентифицирует комментарий
  • -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

DGrady
источник
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
Memin
источник
0

это работает для меня.

from pyjavaproperties import Properties
p = Properties()
p.load(open('test.properties'))
p.list()
print p
print p.items()
print p['name3']
Энди Кироз
источник
Пожалуйста, удалите этот дубликат. Кстати, я проголосовал против вашего другого;)
Джавадба
0

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

** Используется 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
Вайбхав Шукла
источник
Это INI-файл, файл свойств не будет иметь заголовков разделов
Akshay
0

создайте словарь в вашем модуле python и сохраните все в нем и получите к нему доступ, например:

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

Теперь для доступа к нему вы можете просто сделать:

submitButton = driver.find_element_by_id(dict['elementID'])
Винит Сингх
источник
1
Настоятельно рекомендуется поделиться примером кода. Пока ваш ответ очень плохой
Николай Шевченко
@NikolayShevchenko извините за плохое форматирование, я обновил свой ответ
Vineet Singh