python中的属性文件(类似于Java属性)


137

给定以下格式(.properties.ini):

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

对于Java,有一个Properties类,该类提供了解析/与上述格式交互的功能。

python标准库(2.x)中有类似的东西吗?

如果没有,我还有什么其他选择?


5
这不是Java问题。您为什么回滚Java标记删除?
BalusC 2010年

Answers:


69

对于.ini文件,有一个ConfigParser模块,它提供与.ini文件兼容的格式。

无论如何,没有任何可用于解析完整的.properties文件的文件,当我必须这样做时,我只是使用jython(我在谈论脚本)。


10
如果您不想使用Jython,则pyjavaproperties似乎是一个选择:bitbucket.org/jnoller/pyjavaproperties
Hans-Christoph Steiner

2
Java属性文件不等同于.ini文件。pyjavaproperties是正确的答案
igni

2
Alex Matelli在此处stackoverflow.com/a/2819788/15274
pi

自2010年以来一直未维护bitbucket.org/jnoller/pyjavaproperties。它与python 3不兼容。我将使用@pi链接的解决方案。
codyzu

因为这里没有提到,所以我再补充一点,这是不一样的。我不能说Java或Py3,也许它适用于简单的键/值。但是字符串插值的语法不同。该解决方案提供了Python格式,即。%(string)s时(例如对于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辛格

这适用于.ini文件,不适用于.properties文件,因为它们不包含节,并且configParser如果找不到任何节头,则会失败。此外,ini文件可能不包含节,因此此configParser似乎根本不可靠
BiAiB

65

Java属性文件通常也是有效的python代码。您可以将myconfig.properties文件重命名为myconfig.py。然后像这样导入文件

import myconfig

并直接访问属性

print myconfig.propertyName1

11
我喜欢这个主意,但不适用于包含点的属性,即prop.name="val"在这种情况下不起作用。
maxjakob 2012年

36
A java properties file is valid python code:我必须有所不同。一些 Java属性文件将传递有效的python代码,但肯定不是全部。正如@mmjj所说,点是一个问题。无引号的文字字符串也是如此。-1。
Manoj Govindan

24
一个坏主意...因为它坏了。Java prop文件允许使用“:”而不是“ =”; 他们在换行后吃空格;他们不引用字符串。这些都不是“有效的Python”。
丹·H

2
Java属性文件通常不会传递有效的python代码。一种选择是只在python文件中设置属性,然后使用有效的python(例如:MEDIA_ROOT ='/ foo')...
danbgray 2012年

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具有value 的属性"bar" # bat
bonh '19

1
您认为发布旧问题的答案有什么意义?关键是我可以通过将其复制粘贴到我的azure管道之一中来节省时间,而不必自己实现。所以谢谢:)
老和尚

1
爱答案!我对内联注释所做的唯一更改是更改l = line.strip()l = line.split(comment_char)[0].strip(),然后仅检查是否l有一个值,而不是在下一行if l:
Ben Dalling

17

如果可以选择文件格式,我建议使用.ini和Python的ConfigParser,如上所述。如果您需要与Java .properties文件兼容,那么我已经为它编写了一个名为jprops的库。我们使用的是pyjavaproperties,但是遇到各种限制后,我最终实现了自己的。它完全支持.properties格式,包括unicode支持和对转义序列的更好支持。Jprops还可以解析任何类似文件的对象,而pyjavaproperties仅适用于磁盘上的实际文件。


1
我只是尝试了一下。奇迹般有效。为MattGood +1!
丹·H

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}



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

这就是我在项目中所做的事情:我只创建了另一个名为properties.py的.py文件,其中包含我在项目中使用的所有常见变量/属性,并且在任何文件中都需要引用这些变量,

from properties import *(or anything you need)

当我经常更改开发人员的位置并且某些常见变量与本地环境有关时,使用此方法来保持svn的和平。对我来说效果很好,但不确定是否可以在正式的开发环境中建议使用此方法。


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

test.json的内容:{“主机”:“ 127.0.0.1”,“用户”:“ jms”}


2

我创建了一个与Java的Properties类几乎相似的python模块(实际上就像Spring中的PropertyPlaceholderConfigurer一样,它允许您使用$ {variable-reference}来引用已定义的property)

编辑:您可以通过运行命令(当前已针对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')#软糖吧
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”是配置文件中的节名称,“端口”是“ DB”节下的键。)


1

下面的两行代码显示了如何使用Python List Comprehension加载“ java样式”属性文件。

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/


该代码不会关闭文件对象,也不欢迎仅链接回答。
亚里士多德

该解决方案不涵盖多行值或包含等号的值。
Konstantin Tarashchanskiy

1

您可以将参数“ fromfile_prefix_chars”与argparse一起使用,以从配置文件中读取内容,如下所示-

临时

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的文件:

配置文件

[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或--help打印用法摘要
  • -c指定用于标识注释的字符
  • -s prop文件中键和值之间的分隔符
  • 并指定需要解析的属性文件,例如: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

您可以使用以下函数,它是@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']

请删除此重复的帖子。顺便说一句,我没有投票给你另一个;)
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

这是一个ini文件,属性文件将没有节标题
Akshay

0

在python模块中创建一个字典并将所有内容存储到其中并访问它,例如:

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

现在访问它,您只需执行以下操作:

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

1
强烈建议共享一些代码示例。现在您的答案非常糟糕
Nikolai Shevchenko

@NikolayShevchenko很抱歉格式不正确,我已经更新了答案
Vineet Singh
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.