4

I have a question regarding to the python configparser module. I'm using Python 3.x.

I have a lot of .ini-files which are corrupt, respectively in my oppinion defect. e.g. there are values without regarding key e.g.

[SESSIONS_id]
Session_a={F34B3238-EEE5-4006-B19C-AB8CC233D8F0}
Session_b={AF2D869B-0FB1-4287-A10E-82B0884E1CFC}
Session_c={F5A7FA65-2107-4B9B-A7C2-8C89C354D4FF}
={083465AF-DC9E-4FF8-A78F-CC1DF17C84B9}

My Problem here is, that there exists only a Option to "allow no values", I' ve already found that, but how to handle the .ini-files providing values for no keys?

The configparser doesn't read it, so how to repair?

Thanks in advance

Ben
  • 43
  • 3
  • Is [`optionxform`](https://docs.python.org/2/library/configparser.html#ConfigParser.RawConfigParser.optionxform) called on the empty string? If yes, you could provide your implementation, that returns something like `__MISSING__` for an empty option key. – Boldewyn Jan 04 '16 at 16:33
  • Hm. It's not, unfortunately. – Boldewyn Jan 04 '16 at 16:38
  • Can you preprocess the .ini files? Like, `sed -i 's/^=/__MISSING__=/' *.ini`? – Boldewyn Jan 04 '16 at 16:41
  • I already use the RawConfigParser and optionxform to preserve the case-sensitivity for the Option records. To be honest at present I'm a little bit clueless about how powerful optionxform is respectively for what else I could use it right now. To preprocess the .ini-files was my first thought also, but against the background of the huge data I have to proceed and what else I have to do for my task I really would like to prevent another additional Iteration step. At the Moment I see that as a last resort. – Ben Jan 05 '16 at 07:56

1 Answers1

2

You could use comment_prefixes="=#;" so lines starting with an = sign will also be be considered comments:

par = configparser.ConfigParser(comment_prefixes="=#;")
par.read("foo.ini")

print(list((par["SESSIONS_id"]).items()))

[('session_a', '{F34B3238-EEE5-4006-B19C-AB8CC233D8F0}'), ('session_b', '{AF2D869B-0FB1-4287-A10E-82B0884E1CFC}'), ('session_c', '{F5A7FA65-2107-4B9B-A7C2-8C89C354D4FF}')]

Or manually parse the file, first writing to a tempfile and then passing that to configparser:

import configparser
from tempfile import TemporaryFile
t = TemporaryFile("w+")
with open("foo.ini") as f:
    t.writelines(line for line in f if not line.startswith("="))
t.seek(0)
par = configparser.ConfigParser()
par.read_file(t)

print(list((par["SESSIONS_id"]).items()))
[('session_a', '{F34B3238-EEE5-4006-B19C-AB8CC233D8F0}'), ('session_b', '{AF2D869B-0FB1-4287-A10E-82B0884E1CFC}'), ('session_c', '{F5A7FA65-2107-4B9B-A7C2-8C89C354D4FF}')]
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
  • Same here as above: to preprocess the .ini-files was my first thought also, but against the background of the huge data I have to proceed and what else I have to do for my task I really would like to prevent another additional Iteration step. At the Moment I see that as a last resort. I will try the solution with the comment_prefixes, hoping that there will be no conflicts while using "=" also as delimiter. With apologies in advance, I'm really thankful for every answer, but even if I will use it, I do not feel comfortable with it. It seems to be quick and dirty or bad practice, isn't it? – Ben Jan 05 '16 at 08:15
  • Quick 'n dirty, yes, but that doesn't need to be a bad thing. It depends on your needs. If you write one-off code for reading the old configs before removing them, and the code does what you want, there is nothing bad in the solution. If OTOH you write a library, distributed to other devs, this solution is most likely not what you want to do. In this case, it would be better to parse the .ini files yourself, reacting to exceptions in the way _you_ want. – Boldewyn Jan 05 '16 at 09:48
  • @Ben, key value pairings are either going to be separated `=` or `:`, if a line has leading whitespace then an `=` sign it will still be treated as a comment,`=foo=1234` is not valid so you cannot have key/value pairs like that if you have a multiline string the `=` is going to be after the key so unless you expect a multiline string where the value has an equal sign at the very start of one of the multiline string then you are going to be ok. – Padraic Cunningham Jan 05 '16 at 12:52
  • On the other hand if you had a multiline string where you had a leading = sign `if not line.startswith("=")` would allow it so, to see what log all the lines that don't pass `if not line.startswith("="))` – Padraic Cunningham Jan 05 '16 at 12:59
  • Thanks a lot to everybody involved. For the moment I'm feeling comfortable with the "comment_prefixes" Parameter solution. – Ben Jan 05 '16 at 13:49