File properti dalam python (mirip dengan Properti Java)


141

Diberikan format berikut ( .properties or .ini ):

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

Untuk Java, ada kelas Properties yang menawarkan fungsionalitas untuk mengurai / berinteraksi dengan format di atas.

Apakah ada sesuatu yang serupa di python 's standar perpustakaan (2.x)?

Jika tidak, alternatif lain apa yang saya miliki?


5
Ini bukan pertanyaan tentang Java. Mengapa Anda membatalkan penghapusan tag Java?
BalusC

Jawaban:


70

Untuk file .ini ada modul ConfigParser yang menyediakan format yang kompatibel dengan file .ini.

Bagaimanapun tidak ada yang tersedia untuk parsing file .properties lengkap, ketika saya harus melakukannya saya hanya menggunakan jython (saya sedang berbicara tentang scripting).


11
pyjavaproperties tampaknya menjadi pilihan jika Anda tidak ingin menggunakan Jython: bitbucket.org/jnoller/pyjavaproperties
Hans-Christoph Steiner

2
file properti java tidak sama dengan file .ini. pyjavaproperties adalah jawaban yang benar
igni

2
Alex Matelli menyarankan cara mudah untuk mengurai file .properties dengan ConfigParser di sini stackoverflow.com/a/2819788/15274
pi.

bitbucket.org/jnoller/pyjavaproperties belum dikelola sejak 2010. Ini tidak kompatibel dengan python 3. Saya akan menggunakan solusi yang ditautkan oleh @pi.
codyzu

Karena tidak ada di sini disebutkan, izinkan saya menambahkan lagi bahwa ini tidak sama. Saya tidak dapat berbicara untuk Java atau Py3, dan mungkin berfungsi untuk kunci / nilai sederhana. Tetapi sintaks untuk interpolasi string berbeda. Solusi ini menyediakan format Python, mis. % (string) s sementara (misalnya Ant) saya akan menggunakan $ {string}. pymotw.com/2/ConfigParser
mpe

74

Saya bisa mendapatkan ini untuk bekerja ConfigParser, tidak ada yang menunjukkan contoh bagaimana melakukan ini, jadi berikut adalah pembaca python sederhana dari file properti dan contoh file properti. Perhatikan bahwa ekstensinya masih .properties, tetapi saya harus menambahkan tajuk bagian yang mirip dengan apa yang Anda lihat di file .ini ... sedikit bastardization, tetapi berhasil.

File python: PythonPropertyReader.py

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

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

File properti: ConfigFile.properties

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

Untuk fungsionalitas lebih lanjut, baca: https://docs.python.org/2/library/configparser.html


7
Modul ConfigParser telah diubah namanya menjadi configparser dengan Python 3.
Gursewak Singh

Ini untuk file .ini, bukan file .properties karena tidak berisi bagian, dan configParser gagal jika tidak menemukan header bagian. Selain itu, file ini mungkin tidak menyertakan bagian sehingga configParser ini tampaknya tidak dapat diandalkan sama sekali
BiAiB

66

File properti java sering kali merupakan kode python yang valid juga. Anda dapat mengganti nama file myconfig.properties Anda menjadi myconfig.py. Kemudian impor file Anda, seperti ini

import myconfig

dan mengakses properti secara langsung

print myconfig.propertyName1

12
Saya suka idenya, tetapi tidak berhasil untuk properti yang berisi titik, yaitu prop.name="val"tidak akan berfungsi dalam kasus ini.
maxjakob

36
A java properties file is valid python code: Saya harus berbeda. Beberapa file properti Java akan memberikan kode python yang valid, tetapi yang pasti tidak semua. Seperti yang dikatakan @mmjj, titik adalah masalah. Begitu juga string literal yang tidak dikutip. -1.
Manoj Govindan

24
Ide yang Agak Buruk ... karena sudah rusak. File prop Java mengizinkan ":" bukan "="; mereka makan ruang kosong setelah kelanjutan baris; mereka tidak mengutip string. Tak satu pun dari itu adalah "Python valid".
Dan H

2
File properti Java secara umum tidak akan lolos untuk kode python yang valid. Salah satu alternatifnya adalah dengan hanya mengatur properti Anda dalam file python, dan menggunakan python yang valid (misalnya: MEDIA_ROOT = '/ foo') ...
danbgray

3
Ini adalah peretasan yang sebaiknya dihindari. Anda akan mengalami hari yang buruk ketika properti Anda berubah dan file tersebut tidak lagi valid python.
r_2

62

Saya tahu bahwa ini adalah pertanyaan yang sangat lama, tetapi saya membutuhkannya sekarang dan saya memutuskan untuk menerapkan solusi saya sendiri, solusi python murni, yang mencakup sebagian besar kasus penggunaan (tidak semua):

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

Anda dapat mengubah sepmenjadi ':' untuk mengurai file dengan format:

key : value

Kode mem-parsing baris dengan benar seperti:

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

Anda akan mendapatkan dict dengan:

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

1
Solusi terbaik dan persis seperti yang saya cari!
Russell

Perhatikan bahwa ini tidak mendukung komentar di baris yang sama dengan entri seperti foo = "bar" # bat.
ThomasW

1
@ThomasW Jika kita menggunakan Java sebagai standar de-facto, Properties # load akan memperlakukannya sebagai properti foodengan nilai "bar" # bat.
bonh

1
Anda pikir apa gunanya memposting jawaban untuk pertanyaan lama? Intinya adalah saya dapat menghemat waktu hanya dengan menyalin tempel ini, di salah satu pipeline biru saya daripada menerapkannya sendiri. terima kasih :)
biksu tua

1
Suka jawabannya! Satu-satunya perubahan yang saya buat untuk menangani komentar sebaris adalah mengubah l = line.strip()ke l = line.split(comment_char)[0].strip()dan kemudian hanya memeriksa apakah lmemiliki nilai agak pada baris berikutnya dengan if l:.
Ben Dalling

17

Jika Anda memiliki opsi format file, saya sarankan menggunakan .ini dan ConfigParser Python seperti yang disebutkan. Jika Anda membutuhkan kompatibilitas dengan file Java .properties, saya telah menulis perpustakaan untuknya yang disebut jprops . Kami menggunakan properti pyjavaproperties, tetapi setelah menghadapi berbagai batasan, saya akhirnya menerapkan milik saya sendiri. Ini memiliki dukungan penuh untuk format .properties, termasuk dukungan unicode dan dukungan yang lebih baik untuk urutan pelolosan. Jprop juga dapat mengurai objek seperti file apa pun sementara properti pyjavaproperti hanya berfungsi dengan file nyata di disk.


1
Saya baru saja mencobanya. Bekerja seperti pesona. 1 untuk MattGood!
Dan H

1
jika Anda menambahkan pip install dan contoh kode, jawaban Anda akan lebih baik lagi pip install jprops, dengan open (path) sebagai fp: properties = jprops.load_properties (fp) print (properties)
Rubber Duck

11

jika Anda tidak memiliki properti multi baris dan kebutuhan yang sangat sederhana, beberapa baris kode dapat menyelesaikannya untuk Anda:

File t.properties:

a=b
c=d
e=f

Kode 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

Ini sebenarnya bukan properti tetapi Python memiliki pustaka yang bagus untuk mem-parsing file konfigurasi. Lihat juga resep ini: Pengganti python untuk java.util.Properties .


1
Untuk tautan kedua ... Ini tidak lagi dikembangkan secara aktif. Jesse noller telah membuat proyek dari resep ini dengan beberapa perbaikan tidak tersedia di sini. Penulis merekomendasikan proyek itu kepada siapa pun yang menggunakan resep ini. pypi.python.org/pypi/pyjavaproperties
Big Al


3

Ini adalah penggantian satu-ke-satu java.util.Propeties

Dari dokumen:

  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

Anda dapat menggunakan objek seperti file yang ConfigParser.RawConfigParser.readfpdidefinisikan di sini -> https://docs.python.org/2/library/configparser.html#ConfigParser.RawConfigParser.readfp

Tentukan kelas yang menimpa readlineyang menambahkan nama bagian sebelum konten sebenarnya dari file properti Anda.

Saya telah mengemasnya ke dalam kelas yang mengembalikan a dictdari semua properti yang ditentukan.

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

Saya telah menggunakan ini, perpustakaan ini sangat berguna

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

Inilah yang saya lakukan dalam proyek saya: Saya baru saja membuat file .py lain bernama properties.py yang mencakup semua variabel / properti umum yang saya gunakan dalam proyek, dan dalam file apa pun perlu merujuk ke variabel ini, letakkan

from properties import *(or anything you need)

Menggunakan metode ini untuk menjaga keamanan svn ketika saya sering mengubah lokasi dev dan beberapa variabel umum cukup relatif terhadap lingkungan lokal. Berfungsi dengan baik untuk saya tetapi tidak yakin metode ini akan disarankan untuk lingkungan pengembang formal, dll.


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

Isi test.json: {"host": "127.0.0.1", "user": "jms"}


2

Saya telah membuat modul python yang hampir mirip dengan kelas Properties Java (Sebenarnya ini seperti PropertyPlaceholderConfigurer di musim semi yang memungkinkan Anda menggunakan $ {variable-reference} untuk merujuk ke properti yang sudah ditentukan)

EDIT: Anda dapat menginstal paket ini dengan menjalankan perintah (saat ini diuji untuk python 3).
pip install property

Proyek ini dihosting di GitHub

Contoh: (Dokumentasi terperinci dapat ditemukan di sini )

Katakanlah Anda memiliki properti berikut yang ditentukan dalam file my_file.properties

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

Kode untuk memuat properti di atas

from properties.p import Property

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

Misalkan Anda memiliki properti berikut yang ditentukan di file my_file.properties foo = I am awesome bar = $ {chocolate} -bar chocolate = fudge Kode untuk memuat properti di atas prop = Property () prop.load ('path / to / my_file .properties ') prop.get (' foo ') # I am awesome prop.get (' bar ') # fudge-bar
Anand Joshi

Selesai. Semoga membantu
Anand Joshi

2

Jika Anda perlu membaca semua nilai dari bagian di file properti dengan cara yang sederhana:

config.propertiesTata letak file Anda :

[SECTION_NAME]  
key1 = value1  
key2 = value2  

Anda kode:

   import configparser

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

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

Ini akan memberi Anda kamus di mana kuncinya sama seperti di file konfigurasi dan nilainya yang sesuai.

details_dict adalah :

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

Sekarang untuk mendapatkan nilai key1: details_dict['key1']

Menempatkan semuanya dalam metode yang membaca bagian itu dari file konfigurasi hanya sekali (pertama kali metode ini dipanggil selama menjalankan program).

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

Sekarang panggil fungsi di atas dan dapatkan nilai kunci yang diperlukan:

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

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

Memperluas pendekatan yang disebutkan di atas, membaca bagian demi bagian secara otomatis dan kemudian mengakses menurut nama bagian diikuti dengan nama kunci.

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

Untuk mengakses:

config_dict = get_config_section()

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

(di sini 'DB' adalah nama bagian dalam file konfigurasi dan 'port' adalah kunci di bawah bagian 'DB'.)


1

Di bawah 2 baris kode menunjukkan bagaimana menggunakan Pemahaman Daftar Python untuk memuat file properti 'gaya java'.

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

Silakan lihat posting di bawah ini untuk detailnya https://ilearnonlinesite.wordpress.com/2017/07/24/reading-property-file-in-python-using-comprehension-and-generators/


Kode tidak menutup objek file, juga jawaban link saja tidak diterima.
aristotll

Solusi tersebut tidak mencakup nilai multi-garis atau nilai yang menyertakan tanda sama dengan.
Konstantin Tarashchanskiy

1

buat kamus di modul python Anda dan simpan semuanya ke dalamnya dan akses, misalnya:

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

Sekarang untuk mengaksesnya Anda cukup melakukan:

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

1
Sangat disarankan untuk membagikan beberapa contoh kode. Untuk saat ini, jawaban Anda sangat buruk
Nikolai Shevchenko

@NikolayShevchenko maaf untuk format yang buruk, saya telah memperbarui jawaban saya
Vineet Singh

1

Anda dapat menggunakan parameter "fromfile_prefix_chars" dengan argparse untuk membaca dari file konfigurasi seperti di bawah ---

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)

file konfigurasi

--a
hello
--b
hello dear

Jalankan perintah

python temp.py "#config"

1

File Java ini saya tidak memiliki header bagian dan saya menginginkan sebuah dict sebagai hasilnya. Jadi saya hanya menyuntikkan bagian "[ini]" dan membiarkan pustaka konfigurasi default melakukan tugasnya. Hasilnya diubah menjadi dikt:

from configparser import ConfigParser

@staticmethod
    def readPropertyFile(path):
        # /programming/3595363/properties-file-in-python-similar-to-java-properties
        config = ConfigParser()
        s_config= open(path, 'r').read()
        s_config="[ini]\n%s" % s_config
        # https://stackoverflow.com/a/36841741/1497139
        config.read_string(s_config)
        items=config.items('ini')
        itemDict={}
        for key,value in items:
            itemDict[key]=value
        return itemDict

0

Saya melakukan ini menggunakan ConfigParser sebagai berikut. Kode mengasumsikan bahwa ada file bernama config.prop di direktori yang sama tempat BaseTest ditempatkan:

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

Ini adalah apa yang saya tulis untuk mem-parse file dan mengaturnya sebagai variabel env yang melewatkan komentar dan baris nilai non-kunci yang ditambahkan untuk menentukan hg: d

  • -h atau --help mencetak ringkasan penggunaan
  • -c Tentukan karakter yang mengidentifikasi komentar
  • -s Pemisah antara kunci dan nilai dalam file prop
  • dan tentukan file properti yang perlu diurai misalnya: 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

Anda dapat menggunakan fungsi berikut, yang merupakan kode yang dimodifikasi dari @mvallebr. Ini menghormati komentar file properti, mengabaikan baris baru yang kosong, dan memungkinkan mengambil nilai kunci tunggal.

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

ini berhasil untuk saya.

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

Harap hapus postingan duplikat ini. btw saya melakukan upvote yang lain;)
javadba

0

Saya mengikuti pendekatan configparser dan itu bekerja cukup baik untuk saya. Membuat satu file PropertyReader dan menggunakan config parser di sana untuk menyiapkan properti yang sesuai dengan setiap bagian.

** Menggunakan Python 2.7

Isi dari file 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

Isi file skema baca:

from PropertyReader import *

class ReadSchema:

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

Isi dari file .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 adalah file ini, file properti tidak akan memiliki header bagian
Akshay
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.