2

I am using the ConfigParser module in Python 2.6 and I wish to load formatted strings from my configuration file. An example of such a string might be the following:

[Section Name]
#in the config file
#tmp_string has value 'string'
my_string = 'This is a %s' % tmp_string

Is there a nice way to save such strings in the config file? I am not going to know what the value of the string is until I load the config file, so I can't evaluate it and then save it to the file or anything like that. Obviously at the moment, when I load the string and print it out, I get the following:

#config is the ConfigParser
my_string = config.get('Section Name', 'my_string')
print my_string
>>>'This is a %s' % tmp_string 

I would love to get the output:

>>> This is a string

How do you achieve this? I would preferably like to stay with ConfigParser, but another option may be acceptable. (I know you can't just print the string and have it magically appear how you would like it to, I am just trying to demonstrate what I wish to do.)

martineau
  • 119,623
  • 25
  • 170
  • 301
Punson
  • 145
  • 2
  • 10

3 Answers3

4

If tmp_string is defined in the same section of the config file, then you can reference it in other places in the same section using a special format: %(variable_name)s.

So applying it to your example:

myconfig.cfg file

[Section Name]
tmp_string = string  ; must be in the same section
my_string = This is a %(tmp_string)s

Now the value of tmp_string will be "iterpolated" or substituted into the value of my_string when it's retrieved:

try:
    from ConfigParser import ConfigParser
except ModuleNotFoundError:
    from configparser import ConfigParser  # Python 3


config = ConfigParser()
print(config.get('Section Name', 'my_string'))

Output:

This is a string

Note: Normally values outside the current section can't be referenced. However if they were defined in a special section named DEFAULT, their values can be. In other words, the following config file would have produced the same results:

[DEFAULT]
tmp_string = string

[Section Name]
my_string = This is a %(tmp_string)s

If a name is defined in both the DEFAULT section and in the same section as a reference to it, the "local" value in the same section takes precedence and will be the one used.

Python 3 Changes

The ConfigParser module was renamed configparser and an alternative handler for interpolation which implements a more advanced syntax is available via a new ExtendedInterpolation class which added. To enable its use you would need to create an instance of it and use it when instantiating the ConfigParser class — which can be done very succinctly by doing both at once like this:

config = configparser.ConfigParser(interpolation=configparser.ExtendedInterpolation())

This form of interpolation accept strings with the format: ${section:variable_name}. Aside from being slightly more readable than %(variable_name)s, the looked-up variable can be in any specified section, not just a special one named DEFAULT. If the section: part is left out, the variable name must be in the current section (or the special DEFAULT section if there is one).

martineau
  • 119,623
  • 25
  • 170
  • 301
2

The same way the docs already explain:

my_string='This is a %(tmp_string)s'
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
1

These days the docs also specify a way to use ${} as your formatter, which I found easier to both read and use, instead of %()s. This is quite simple to achieve:

consider the following config filed, named .configfile:

[arbitrarySectionName]
tmp_string = any section

[Section Name]
my_string = Now you can read from ${arbitrarySectionName:tmp_string} not just DEFAULT

and to interpret this properly you'll do in your module:

import configparser
config = configparser.ConfigParser(interpolation=configparser.ExtendedInterpolation())
config.read('.configfile')
print(config.get('Section Name', 'my_string'))

Output:

Now you can read from any section not just DEFAULT

barshopen
  • 1,190
  • 2
  • 15
  • 28