13

I have a config file using configParser:

<br>
[ section one ]<br>
one = Y,Z,X <br><br>
[EG 2]<br>
ias = X,Y,Z<br>

My program works fine reading and processing these values.

However some of the sections are going to be quite large. I need a config file that will allow the values to be on a new line, like this:

[EG SECTION]<br>
EG=<br>
item 1 <br>
item 2 <br>
item 3<br>
etc...

In my code I have a simple function that takes a delimiter (or separator) of the values using string.split() obviously now set to comma. I have tried the escape string of \n which does not work.

Does anyone know if this is possible with python's config parser?
http://docs.python.org/library/configparser.html

# We need to extract data from the config 
def getFromConfig(currentTeam, section, value, delimeter):
    cp = ConfigParser.ConfigParser()
    fileName = getFileName(currentTeam)
    cp.read(fileName)
    try:
        returnedString = cp.get(section, value)
    except: # The config file could be corrupted
        print( "Error reading " + fileName + " configuration file." )
        sys.exit(1) #Stop us from crashing later
    if delimeter != "": # We may not need to split
        returnedList = returnedString.split(delimeter)
    return returnedList

I would use for this:

taskStrings = list(getFromConfig(teamName, "Y","Z",","))
martineau
  • 119,623
  • 25
  • 170
  • 301
JP29
  • 633
  • 4
  • 13
  • 25

3 Answers3

15

The ConfigParser _read() method's docstring says:

Continuations are represented by an embedded newline then leading whitespace.

Or alternatively (as the version in Python 3 puts it):

Values can span multiple lines, as long as they are indented deeper than the first line of the value.

This feature provides a means to split values up and "continue" them across multiple lines. For example, say you had a config file named 'test.ini' which contained:

[EG SECTION]<br>
EG=<br>
  item 1<br>
  item 2<br>
  item 3<br>

You could read the value of EG in the EG SECTION into a list with code like this:

try:
    import ConfigParser as configparser
except ImportError:  # Python 3
    import configparser

cp = configparser.ConfigParser()
cp.read('test.ini')

eg = cp.get('EG SECTION', 'EG')
print(repr(eg))  # -> '\nitem 1\nitem 2\nitem 3'

cleaned = [item for item in eg.strip().split('\n')]
print(cleaned)  # -> ['item 1', 'item 2', 'item 3']
martineau
  • 119,623
  • 25
  • 170
  • 301
  • Is any level of nesting possible? Like, say I have an intended section in which one of the value is again sub-intended. This is again having one value which is sub-intended and so forth! – Nishant Jan 21 '18 at 17:19
  • 1
    @Nishant: Assuming you mean "indented": First of all you could easily answer the question yourself (by trying it, if nothing else). However to save you the trouble — it doesn't matter how much items are indented, just whether they are or not. – martineau Jan 21 '18 at 17:33
  • I meant indented sorry. I got the part that it could be indented to any depth, but what I meant is what if there is an additional item in that *deeply* indented stuff which has *further deeply* indented items? Usual case of nesting I mean. I guess the third level in this case. I hope you get it, otherwise its fine :-) I will try it out and probably post another question! – Nishant Jan 21 '18 at 17:59
  • 1
    The `configparser` module doesn't support nested sections, if that's what you mean. In addition, the values it returns are always strings, so it's unclear to me what you want to do and are asking about. – martineau Jan 21 '18 at 18:32
  • Yes I was asking about nested sections. I think that answers my question. Thank You very much. – Nishant Jan 22 '18 at 06:33
  • 1
    @Nishant: There's a third-party module named [`ConfigObj`](http://www.voidspace.org.uk/python/configobj.html) that supports nested sections (as well as many other things). However it doesn't use whitespace to indicate the nesting — although you can put some in if you want. Nested section names just have extra brackets around them. i.e. `[[sub-section]]`. – martineau Jan 22 '18 at 15:17
  • 1
    Here's were to get the current version of [ConfigObj](https://pypi.org/project/configobj/) nowadays (via pypi.org). – martineau Oct 12 '19 at 17:18
2

It seems possible. In my own config file, for example, I have a list object with tuples:

[root]
path: /
redirectlist: [ ( r'^magic', '/file' ),
    ( r'^avplay', '/file' ),
    ( r'^IPTV', '/file' ),
    ( r'^box', '/file' ),
    ( r'^QAM', '/qam' ),
    ( r'.*opentv.*', '/qam' ),
    ( r'.+', '/file' ) ]

and I do:

redirectstr = _configdict.get('root', 'redirectlist')
redirects = eval(redirectstr)

note that I am actually eval'ing that line, which may cause security breaches if used in the wild.

Andre Blum
  • 391
  • 3
  • 6
  • 7
    It seems you could do this safely by simply replacing `eval` with `ast.literal_eval`, unless you're allowing the user to input objects that aren't simple python objects (dictionaries, strings, lists, tuples, floats and integers). – mgilson Jul 09 '12 at 17:11
0

https://docs.python.org/3/library/configparser.html#supported-ini-file-structure

Values can also span multiple lines, as long as they are indented deeper than the first line of the value. Depending on the parser’s mode, blank lines may be treated as parts of multiline values or ignored.

[Multiline Values]
chorus: I'm a lumberjack, and I'm okay
    I sleep all night and I work all day
[Section]
key = multiline
  value with a gotcha

 this = is still a part of the multiline value of 'key'

for your case

[EG SECTION]<br>
EG=<br>
item1<br>
item2<br>
item3<br>

eg = cp.get('EG SECTION', 'EG')
print(eg)

would get some error :Source contains parsing errors: This is "no value" error.

item 1 would be considered as new option with no value item 2,3 are the same, while the EG=
get blank value

if you modify them with "allow_no_value=True"

[EG SECTION]<br>
EG=<br>
item1<br>
item2<br>
item3<br>

cp = ConfigParser.ConfigParser(allow_no_value=True)
eg = cp.get('EG SECTION', 'EG')
print(eg)

you would get blank screen for output, because EG=

Finally,add some indents and split function

[EG SECTION]<br>
EG=<br>
 item1<br>
 item2<br>
 item3<br>

cp = ConfigParser.ConfigParser()
eg = cp.get('EG SECTION', 'EG').split('\n')
print(eg)

you would get ['item1', 'item2', 'item3']