Tệp thuộc tính trong python (tương tự như Thuộc tính Java)


137

Cho định dạng sau ( .properations hoặc .ini ):

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

Đối với Java, có lớp Properties cung cấp chức năng phân tích / tương tác với định dạng trên.

Có cái gì đó tương tự trong thư viện tiêu chuẩn của python (2.x) không?

Nếu không, tôi có những lựa chọn thay thế nào khác?


5
Đây không phải là một câu hỏi Java. Tại sao bạn lại khôi phục việc xóa thẻ Java?
BalusC

Câu trả lời:


69

Đối với các tệp .ini có mô-đun ConfigParser cung cấp định dạng tương thích với các tệp .ini.

Dù sao, không có gì để phân tích các tệp .properations hoàn chỉnh, khi tôi phải làm điều đó, tôi chỉ cần sử dụng jython (Tôi đang nói về kịch bản).


10
pyjavaproperies dường như là một lựa chọn nếu bạn không muốn sử dụng Jython: bitbucket.org/jnoller/pyjavaproperies
Hans-Christoph Steiner

2
tệp thuộc tính java không tương đương với tệp .ini. pyjavaproperies là câu trả lời đúng
igni

2
Alex Matelli đã đề xuất một cách dễ dàng để phân tích các tệp .properations với ConfigParser tại đây stackoverflow.com/a/2819788/15274
pi.

bitbucket.org/jnoller/pyjavaproperIES đã không được duy trì từ năm 2010. Nó không tương thích với python 3. Tôi sẽ sử dụng các giải pháp được liên kết bởi @pi.
codyzu

Vì không có ở đây nó được đề cập, hãy để tôi thêm một lần nữa rằng điều này không giống nhau. Tôi không thể nói cho Java hoặc Py3 và có thể nó hoạt động với các khóa / giá trị đơn giản. Nhưng cú pháp cho phép nội suy chuỗi là khác nhau. Giải pháp này cung cấp định dạng Python, tức là. % (chuỗi) s while (ví dụ: Ant) Tôi sẽ sử dụng $ {string}. pymotw.com/2/ConfigParser
mpe

74

Tôi đã có thể làm việc này ConfigParser, không ai đưa ra bất kỳ ví dụ nào về cách thực hiện việc này, vì vậy đây là một trình đọc python đơn giản của tệp thuộc tính và ví dụ về tệp thuộc tính. Lưu ý rằng phần mở rộng vẫn còn .properties, nhưng tôi đã phải thêm một tiêu đề phần tương tự như những gì bạn thấy trong các tệp .ini ... một chút của sự khốn, nhưng nó hoạt động.

Tệp python: PythonPropertyReader.py

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

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

Các tập tin tài sản: ConfigFile.properties

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

Để biết thêm chức năng, hãy đọc: https://docs.python.org/2/l Library / configparser.html


5
Mô-đun ConfigParser đã được đổi tên thành configparser trong Python 3.
Gursewak Singh

Đây là cho các tệp .ini, không phải các tệp .properations vì chúng không chứa các phần và configParser không thành công nếu nó không tìm thấy bất kỳ tiêu đề phần nào. Hơn nữa, các tệp ini có thể không bao gồm các phần nên configParser này có vẻ không đáng tin chút nào
BiAiB

65

Một tệp thuộc tính java thường là mã python hợp lệ là tốt. Bạn có thể đổi tên tệp myconfig.properIES của mình thành myconfig.py. Sau đó, chỉ cần nhập tệp của bạn, như thế này

import myconfig

và truy cập các thuộc tính trực tiếp

print myconfig.propertyName1

11
Tôi thích ý tưởng này, nhưng nó không hoạt động đối với các thuộc tính có chứa dấu chấm, tức prop.name="val"là sẽ không hoạt động trong trường hợp này.
maxjakob

36
A java properties file is valid python code: Tôi phải khác biệt. Một số tệp thuộc tính Java sẽ chuyển cho mã python hợp lệ, nhưng chắc chắn không phải tất cả. Như @mmjj nói chấm là một vấn đề. Vì vậy, các chuỗi chữ không được trích dẫn. -1.
Manoj Govindan

24
Một ý tưởng khá tệ ... vì nó đã bị phá vỡ. Các tệp prop Java cho phép ":" thay vì "="; họ ăn khoảng trắng sau khi nối tiếp; họ không trích dẫn chuỗi. Không ai trong số đó là "Python hợp lệ".
Dan H

2
Các tệp thuộc tính Java nói chung sẽ không chuyển cho mã python hợp lệ. Một cách khác là chỉ đặt thuộc tính của bạn trong tệp python và sử dụng python hợp lệ (ví dụ: MEDIA_ROOT = '/ foo') ...
danbgray

3
Đây là một hack tốt nhất nên tránh. Bạn sẽ có một ngày tồi tệ khi tài sản của bạn thay đổi và tập tin không còn là python hợp lệ.
r_2

59

Tôi biết rằng đây là một câu hỏi rất cũ, nhưng tôi cần nó ngay bây giờ và tôi quyết định thực hiện giải pháp của riêng mình, một giải pháp python thuần, bao gồm hầu hết các trường hợp sử dụng (không phải tất cả):

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

Bạn có thể thay đổi septhành ':' để phân tích các tệp có định dạng:

key : value

Mã phân tích chính xác các dòng như:

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

Bạn sẽ nhận được một lệnh với:

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

1
Giải pháp đỉnh cao và chính xác là những gì tôi đang tìm kiếm!
Russell

Lưu ý rằng điều này không hỗ trợ nhận xét trên cùng một dòng với các mục như foo = "bar" # bat.
ThomasW

1
@ThomasW Nếu chúng tôi sử dụng Java làm tiêu chuẩn thực tế, tải thuộc tính # sẽ coi đó là một thuộc tính foocó giá trị "bar" # bat.
bonh

1
Bạn nghĩ điểm nào trong việc đăng câu trả lời cho một câu hỏi cũ? Vấn đề là tôi đã có thể tiết kiệm thời gian bằng cách sao chép dán cái này, vào một trong những đường ống màu xanh của tôi chứ không phải tự thực hiện nó. cảm ơn :)
thầy tu

1
Yêu câu trả lời! Thay đổi duy nhất tôi đã thực hiện để xử lý các nhận xét nội tuyến là thay đổi l = line.strip()thành l = line.split(comment_char)[0].strip()và sau đó chỉ kiểm tra xem lcó giá trị nào trên dòng tiếp theo không if l:.
Ben Dalling

17

Nếu bạn có một tùy chọn định dạng tệp, tôi khuyên bạn nên sử dụng .ini và Python's ConfigParser như đã đề cập. Nếu bạn cần khả năng tương thích với các tệp .properations của Java, tôi đã viết một thư viện cho nó được gọi là jprops . Chúng tôi đã sử dụng pyjavaproperies, nhưng sau khi gặp phải những hạn chế khác nhau, cuối cùng tôi đã tự mình thực hiện. Nó có hỗ trợ đầy đủ cho định dạng .properations, bao gồm hỗ trợ unicode và hỗ trợ tốt hơn cho các chuỗi thoát. Jprops cũng có thể phân tích cú pháp bất kỳ đối tượng giống như tệp nào trong khi pyjavaproperies chỉ hoạt động với các tệp thực trên đĩa.


1
Tôi chỉ thử cái này Hoạt động như một lá bùa. +1 cho Matt Tốt!
Đàn H

1
nếu bạn thêm cài đặt pip và một ví dụ mã, câu trả lời của bạn sẽ tốt hơn khi cài đặt pip, với mở (đường dẫn) là fp: property = jprops.load_properies (fp) print (property)
Rubber Duck

10

nếu bạn không có thuộc tính nhiều dòng và một nhu cầu rất đơn giản, một vài dòng mã có thể giải quyết nó cho bạn:

Tập tin t.properties:

a=b
c=d
e=f

Mã 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

Đây không phải là thuộc tính chính xác nhưng Python có một thư viện đẹp để phân tích tệp cấu hình. Cũng xem công thức này: Một thay thế python cho java.util.ProperIES .


1
Đối với liên kết thứ hai ... Điều này không còn được phát triển tích cực. Jesse noller đã tạo ra một dự án từ công thức này với một số bản sửa lỗi không có sẵn ở đây. Tác giả đề xuất dự án đó cho bất cứ ai sử dụng công thức này. pypi.python.org/pypi/pyjavaproperIES
Big Al


3

Đây là sự thay thế một-một của java.util.Propeties

Từ tài liệu:

  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

Bạn có thể sử dụng một đối tượng giống như tệp ConfigParser.RawConfigParser.readfpđược xác định tại đây -> https://docs.python.org/2/l Library / configparser.html #ConPigParser.RawConfigParser.readfp

Xác định một lớp ghi đè readlinethêm tên phần trước nội dung thực tế của tệp thuộc tính của bạn.

Tôi đã đóng gói nó vào lớp trả về một dicttrong tất cả các thuộc tính được xác định.

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

tôi đã sử dụng cái này, thư viện này rất hữu ích

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

Đây là những gì tôi đang làm trong dự án của mình: Tôi chỉ cần tạo một tệp .py khác có tên là property.txt bao gồm tất cả các biến / thuộc tính phổ biến mà tôi đã sử dụng trong dự án và trong bất kỳ tệp nào cần tham chiếu đến các biến này, hãy đặt

from properties import *(or anything you need)

Đã sử dụng phương pháp này để giữ hòa bình svn khi tôi thay đổi vị trí dev thường xuyên và một số biến phổ biến khá tương đối với môi trường địa phương. Hoạt động tốt với tôi nhưng không chắc phương pháp này sẽ được đề xuất cho môi trường dev chính thức, v.v.


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

Nội dung của test.json: {"host": "127.0.0.1", "user": "jms"}


2

Tôi đã tạo một mô-đun python gần giống với lớp Properties của Java (Trên thực tế, nó giống như PropertyPlaceholderConfigker vào mùa xuân cho phép bạn sử dụng $ {tham chiếu biến} để tham chiếu đến thuộc tính đã được xác định)

EDIT: Bạn có thể cài đặt gói này bằng cách chạy lệnh (hiện đang được thử nghiệm cho python 3).
pip install property

Dự án được lưu trữ trên GitHub

Ví dụ: (Tài liệu chi tiết có thể tìm thấy ở đây )

Giả sử bạn có các thuộc tính sau được xác định trong tệp my_file.properIES

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

Mã để tải các thuộc tính trên

from properties.p import Property

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

Giả sử bạn có các thuộc tính sau được xác định trong tệp my_file.properIES foo = I am awesome bar = $ {chocolate} -bar chocolate = fudge Code để tải các thuộc tính trên prop = property () prop.load ('path / to / my_file .properies ') prop.get (' foo ') # Tôi là prop.get tuyệt vời (' bar ') # fudge-bar
Anand Joshi

Làm xong . Hy vọng nó sẽ giúp
Anand Joshi

2

Nếu bạn cần đọc tất cả các giá trị từ một phần trong tệp thuộc tính một cách đơn giản:

config.propertiesBố cục tệp của bạn :

[SECTION_NAME]  
key1 = value1  
key2 = value2  

Bạn mã:

   import configparser

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

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

Điều này sẽ cung cấp cho bạn một từ điển trong đó các khóa giống như trong tệp cấu hình và các giá trị tương ứng của chúng.

details_dict Là :

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

Bây giờ để lấy giá trị của key1: details_dict['key1']

Đặt tất cả vào một phương thức chỉ đọc phần đó từ tệp cấu hình một lần (lần đầu tiên phương thức được gọi trong khi chạy chương trình).

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

Bây giờ gọi hàm trên và nhận giá trị của khóa được yêu cầu:

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

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

Mở rộng cách tiếp cận được đề cập ở trên, đọc phần theo phần tự động và sau đó truy cập theo tên phần theo sau là tên khóa.

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

Để truy cập:

config_dict = get_config_section()

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

(ở đây 'DB' là tên phần trong tệp cấu hình và 'cổng' là khóa trong phần 'DB'.)


1

Bên dưới 2 dòng mã cho thấy cách sử dụng Hiểu danh sách Python để tải tệp thuộc tính 'kiểu java'.

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

Vui lòng xem bài viết dưới đây để biết chi tiết https://ilearnonlinesite.wordpress.com/2017/07/24/reading-property-file-in-python-USE-comprehension-and-generators/


Mã không đóng đối tượng tập tin, liên kết chỉ trả lời không được chào đón.
aristotll

Giải pháp đó không bao gồm các giá trị nhiều dòng hoặc các giá trị bao gồm một dấu bằng.
Konstantin Tarashchanskiy

1

bạn có thể sử dụng tham số "fromfile_prefix_chars" với argparse để đọc từ tệp cấu hình như bên dưới ---

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)

tập tin cấu hình

--a
hello
--b
hello dear

Chạy lệnh

python temp.py "#config"

0

Tôi đã làm điều này bằng cách sử dụng ConfigParser như sau. Mã này giả định rằng có một tệp có tên config.prop trong cùng thư mục nơi BaseTest được đặt:

cấu hình

[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

Đây là những gì tôi đã viết để phân tích tệp và đặt nó dưới dạng các biến env bỏ qua các bình luận và các dòng giá trị không khóa được thêm vào để chỉ định hg: d

  • -h hoặc - trợ giúp tóm tắt sử dụng in
  • -c Chỉ định char xác định nhận xét
  • -s Dấu phân cách giữa khóa và giá trị trong tệp prop
  • và chỉ định tệp thuộc tính cần được phân tích cú pháp, ví dụ: python EnvParamSet.py -c # -s = env.properies

    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 đã phát hành thư viện Formsafe Config , phân tích cú pháp các tệp thuộc tính và một số phần mở rộng dựa trên JSON. Thư viện của Lightbend chỉ dành cho JVM, nhưng dường như nó được chấp nhận rộng rãi và hiện có các cổng bằng nhiều ngôn ngữ, bao gồm cả Python: https://github.com/chimpler/pyhocon


0

Bạn có thể sử dụng chức năng sau, đây là mã sửa đổi của @mvallebr. Nó tôn trọng các bình luận tệp thuộc tính, bỏ qua các dòng mới trống và cho phép truy xuất một giá trị khóa duy nhất.

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

cái này hiệu quả với tôi

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

Vui lòng xóa bài đăng trùng lặp này. btw Tôi đã nâng cấp người khác của bạn;)
javadba

0

Tôi đã làm theo cách tiếp cận configparser và nó hoạt động khá tốt đối với tôi. Tạo một tệp PropertyReader và sử dụng trình phân tích cú pháp cấu hình ở đó để sẵn sàng thuộc tính tương ứng với từng phần.

** Đã sử dụng Python 2.7

Nội dung của tập tin 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

Nội dung của tệp lược đồ đọc:

from PropertyReader import *

class ReadSchema:

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

Nội dung của tệp .properations:

[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

Đây là tệp ini, tệp thuộc tính sẽ không có tiêu đề phần
Akshay

0

tạo một từ điển trong mô-đun python của bạn và lưu trữ mọi thứ vào đó và truy cập nó, ví dụ:

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

Bây giờ để truy cập nó, bạn chỉ cần làm:

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

1
Rất khuyến khích chia sẻ một số mẫu mã. Bây giờ câu trả lời của bạn rất kém
Nikolai Shevchenko

@NikolayShevchenko xin lỗi vì định dạng kém, tôi đã cập nhật câu trả lời của mình
Vineet Singh
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.