3

I would like to use a configuration file with some simple math expressions like adding or substracting.
For example:

[section]
a = 10
b = 15
c = a-5
d = b+c

Is there any way to do this using a ConfigParser module? I found some examples of using strings as a kind of variables in config files, but if i'm using it i get a not evaluated strings (and i have to parse it in my python code).

If it's not possible in ConfigParser is there any module you recommend?

KozaK
  • 31
  • 1
  • 3
  • 5
    calculations is not what configuration files are for. – SilentGhost Jan 11 '11 at 13:29
  • 2
    @SilentGhost: You shouldn't do too much processing, but there are situations where you want to say "x is 5 bigger than y", while being able to change y. This is a lot neater than specifying x_ydiff and sorting out precedence rules and so on. – Thomas K Jan 11 '11 at 13:51
  • You could use Vinay Sajip's [`config` module](http://www.red-dove.com/config-doc) which was his entry in the comp.lang.python [ConfigParserShootout](http://wiki.python.org/moin/ConfigParserShootout) which allows [using expressions](http://www.red-dove.com/config-doc/#using-expressions) in config files. Alternatively you could probably put one together fairly easily utilizing Steven Siew's [SimpleCalc.py](http://pyparsing.wikispaces.com/file/view/SimpleCalc.py) from the [pyparsing - Examples](http://pyparsing.wikispaces.com/Examples) page. – martineau Jan 11 '11 at 18:42

3 Answers3

9

Why use ConfigParser? Why not just

config.py:

a = 10
b = 15
c = a-5
d = b+c

script.py:

import config
print(config.c)
# 5
print(config.d)
# 20
unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
2

If you must you can do something like this:

example.conf :

[section]
a = 10
b = 15
c = %(a)s+%(b)s
d = %(b)s+%(c)s

and in your script you can do:

import ConfigParser

config = ConfigParser.SafeConfigParser()
config.readfp(open('example.conf'))

print config.get('section', 'a')
# '10'
print config.get('section', 'b')
# '15'
print config.get('section', 'c')
# '10+15'
print config.get('section', 'd')
# '15+10+15'

and you can eval the expression :

print eval(config.get('section', 'c'))
# 25
print eval(config.get('section', 'd'))
# 40

If i may suggest i think that ConfigParser modules classes are missing a function like this, i think the get() method should allow to pass a function that will eval the expression :

def my_get(self, section, option, eval_func=None):

    value = self.get(section, option)
    return eval_func(value) if eval_func else value

setattr(ConfigParser.SafeConfigParser, 'my_get', my_get)


print config.my_get('section', 'c', eval)
# 25

# Method like getint() and getfloat() can just be writing like this:

print config.my_get('section', 'a', int)
# 10
mouad
  • 67,571
  • 18
  • 114
  • 106
  • 1
    Randomly calling eval on options in your config file is probably not a habit to get into, though. A python file you can expect to be executable, but you don't expect to be running arbitrary instructions from inside config files. – Thomas K Jan 11 '11 at 14:39
  • While I like the whole idea of semi-executable config files, I don't care much for the `%(...)s` notation this approach requires. – martineau Jan 11 '11 at 18:01
1

One approach that some projects use is to make your configuration file a Python module. Then simply import it (or use exec) to run the contents. That gives you a lot of power, although obviously there are some security concerns depending on where you use it ("just paste these lines into your .whateverrc.py file...").

Thomas K
  • 39,200
  • 7
  • 84
  • 86
  • One advantage to using `exec` is that the file can have any or no extension. I believe it must be named *.py to be imported. – martineau Jan 11 '11 at 14:42
  • @martineau: It also doesn't have to be in the PYTHONPATH. IPython's new config system uses `exec` (although the file still has a .py extension, not least to make it clear what it is). – Thomas K Jan 11 '11 at 15:54