12

I have a file with the format

VarName=Value
.
.

I want to read it into a hash such that H("VarName") will return the value.

What would be a quick way? (read a set of strings, split all of them where the equality sign is, and then put it into a hash?

I am working with python.

shahjapan
  • 13,637
  • 22
  • 74
  • 104
jury
  • 121
  • 1
  • 1
  • 3

10 Answers10

22

The oneliner answer:

H = dict(line.strip().split('=') for line in open('filename.txt'))

(optionally use .split() with maxsplit=1 if the values could also contain the "=" character)

Steven
  • 28,002
  • 5
  • 61
  • 51
  • I'm sorry, but this is a -1. This doesn't obey several things that are valid per the grammar that is valid for a Properties file. See the following link for more details of what is missing from this answer: https://docs.oracle.com/cd/E23095_01/Platform.93/ATGProgGuide/html/s0204propertiesfileformat01.html. Properties files, similar to JSON, does not have a very complex grammar, but you need to obey it none-the-less. – searchengine27 Oct 02 '17 at 22:54
10

Maybe ConfigParser can help you.

rubik
  • 8,814
  • 9
  • 58
  • 88
  • 11
    -1 Except that ConfigParser will throw a NoSectionError if there aren't any section headers. – samwyse Jul 11 '14 at 22:23
8

Taking @Steven's answer doesn't account comments and newlines in the properties file, this one does:

H = dict(line.strip().split('=') for line in open('file.properties') if not line.startswith('#') and not line.startswith('\n'))  
GBF_Gabriel
  • 2,636
  • 2
  • 17
  • 15
  • I'm sorry but this has the same problem as @Steven. If this obeyed the grammar I would remove the downvote, or if the answer at least acknowledged that this is not parsing a properties file. – searchengine27 Oct 02 '17 at 22:55
8
d = {}
with open('filename') as f:
    for line in f:
        key, value = line.split('=')
        d[key] = value

Edit: As suggested by foret, you could change it to

    for line in f:
        tokens = line.split('=')
        d[tokens[0]] = '='.join(tokens[1:])

which would handle the case where equals signs were allowed in the value, but would still fail if the name could have equals signs as well -- for that you would need a true parser.

user470379
  • 4,879
  • 16
  • 21
  • 2
    You can just do `for line in f`. – Björn Pollex Oct 22 '10 at 14:32
  • 2
    What if value contains '='? =) – foret Oct 22 '10 at 14:39
  • Then either you need a full-on parser for lines like `'x=y'="\"'z'=a\""` or if you can't quote parts the file format is ambiguous: does `x=y=z` mean `x -> y=z` or `x=y -> z`? – user470379 Oct 22 '10 at 14:46
  • The only reason I'm not downvoting this is because you call out in your answer `for that you would need a true parser`, which implies this is not parsing a properties file. I would still prefer it if you explicitly called out that this is not parsing a .properties file grammar, but this is a start at least. – searchengine27 Oct 02 '17 at 22:57
3

Or ConfigObj

mmmmmm
  • 32,227
  • 27
  • 88
  • 117
3

The csv module will let you do this easily enough:

import csv
H = dict([(row[0], row[1]) for row in csv.reader(open('the_file', 'r'), delimiter='=' )])
GreenMatt
  • 18,244
  • 7
  • 53
  • 79
2

this may be a stupid answer but who know maybe it can help you :)

change the extension of your file to .py, and do necessary change like this:

file.py

VarName="Value"   # if it's a string
VarName_2=1
# and you can also assign a dict a list to a var, how cool is that ?

and put it in your package tree or in sys.path, and now you can call it like this in the script when you want to use it:

>>> import file
>>> file.VarName
'Value'

why i'm writing this answer it's because ,what the hell is this file ? i never see a conf file like this , no section no nothing ? why you want to create a config file like this ? it look like a bad config file that should look like the Django settings, and i prefer using a django setting-like config file when ever i can.

Now you can put your -1 in the left :)

mouad
  • 67,571
  • 18
  • 114
  • 106
  • It's a Java properties file. Pretty standard, which makes it a shame that ConfigParser throws a NoSectionError if there aren't any sections. I should submit a feature request for that. – samwyse Jul 11 '14 at 22:28
  • I do like that you're thinking outside the box, but this will break on a line like `VarName:value`, which both breaks on the `:` character, and the fact that your `value` does not have quotes around it. – searchengine27 Oct 02 '17 at 22:59
  • Also, @samwyse: .cfg files, while not having as centralized of a formal grammar as a .properties file, is commonly interpreted differently than .properties. `ConfigParser` is a library to understand .cfg files, so if you write a bug against that library for not reading .properties, they are likely to kick it back and reject it - I would anyway. .properties files are not the responsibility of a .cfg parser. .cfg files require the existence of one section in most .cfg handlers, which is why that exception is thrown. – searchengine27 Oct 02 '17 at 23:31
2

For python2 there is a jproperties https://pypi.python.org/pypi/jproperties/1.0.1

For python2/3 there is javaproperties http://javaproperties.readthedocs.io/en/v0.1.0/

as simple as:

import os, javaproperties
with open(file, 'rb') as f:
    properties_dict = javaproperties.load(f)
Igor A
  • 311
  • 3
  • 10
  • This is honestly the only complete solution here that actually 100 percent solves the problem of the OP. The only problem might be the use of third party libraries that might be restricted by his organization, as frequently happens in the corporate world. A solution I have to the same problem requires the use of a separate library as well, so I don't have a better solution to this, necessarily - just different. – searchengine27 Oct 02 '17 at 23:03
0

If you need to read all values from a section in properties file in a simple manner:

Your config.properties file layout :

[SECTION_NAME]  
key1 = value1  
key2 = value2  

You code:

import configparser

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

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

This will give you a dictionary where keys are same as in config file and their corresponding values.

details_dict becomes

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

Now to get key1's value :

value_1 = details_dict['key1']

Putting it all in a method which reads that section from config file only once(the first time the method is called during a program run).

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

Now call the above function and get the required key's value :

config_details = get_config_dict()
key_1_value = config_details['key1'] 
MANU
  • 1,358
  • 1
  • 16
  • 29
0

OK nobody else in the answers has mentioned it, so I guess I'm going to. If you're writing Python, and have control over your interpreter, maybe you can force the use of the Jython interpreter.

Jython is a Python interpreter implemented entirely in Java. You have all the Python standard libraries at your fingertips, with the additional advantage of all your Java SE libraries available.

I haven't actually executed any of the following (think of it more like psudeo-code without exception handling), but you can mix and match Python and Java libraries, and your code might end up looking something like:

from java.util import Properties
from java.io import File, FileInputStream
import os
javasPropertyObject = Properties()
pathToPropFile = os.path.join('path', 'to', 'property', 'file.properties')
if os.path.isfile(pathToPropFile):
    #this is java.io.File, not Python's file descriptor
    propFile = File(pathToPropFile )
    javasFileInputStreamObject = FileInputStream(propFile)
    javasPropertyObject.load(javasFileInputStreamObject)

    #now we can pull out Java properties as defined by the .property file grammar
    myProp = javasPropertyObject.getProperty('myPropName')

where a file like this will be valid, that wouldn't in the simple split on '=' solutions:

myPropName1:value
myPropName2=value
myPropName3=\
value
#this is a = comment
myPropName4:my \
value
myPropNameWithUnicode=\u0009

The downside, is that you lose your ability to be portable among varying Python interpreters and now you're locked into Jython. You would be locked into a library if you attempt that approach as well. The reason why I like Jython is that your added flexibility with having all of the Java SE libraries available.

searchengine27
  • 1,449
  • 11
  • 26