1

I sometimes get an .ini file that looks like this after changing and deleting values:

[Section A]
x = 1
d = 2



[Section B]
a = 3

Is there an easy way to keep it clean and remove those blank lines between the sections?

Dima
  • 459
  • 1
  • 3
  • 13

4 Answers4

1

If you want to use a strictly python solution, you can create a temp file, copy over the non empty lines, and then replace the file.

from tempfile import mkstemp
from os import close
from shutil import move

def replace(filename, name, new_value):
    fd, path = mkstemp()
    with open(path,'w') as tmpfile:
        with open(filename) as csv:
            for line in cvs:
                if line.strip()!="":
                    tmpfile.write(line)
    close(fd)
    move(path, filename)
galimay
  • 415
  • 3
  • 4
0

Probably easier using a tool like grep

$ grep -v "^\\s*$" foo > bar

but if you have to use Python then check out this answer.

Community
  • 1
  • 1
TimGJ
  • 1,584
  • 2
  • 16
  • 32
  • It just seems weird that the configparser module doesn't keep the ini files tidy on its own. – Dima Apr 25 '17 at 22:16
  • Not that I have the skills to do so, but how hard would it be to add such a function to the official configparser library? – Dima Apr 26 '17 at 19:31
  • @Dima have a look at https://github.com/python/cpython/blob/3.6/Lib/configparser.py#L904 ... probably a bit of work, but nothing too difficult. – fiacre Apr 26 '17 at 20:02
  • @Dima you can fork it, make changes and post a merge request, see https://akrabat.com/the-beginners-guide-to-contributing-to-a-github-project/ – fiacre Apr 27 '17 at 12:51
0

Just use sed:

sed '/^$/d' myfile.ini

works

fiacre
  • 1,150
  • 2
  • 9
  • 26
  • I've never heard of sed. Is it part of the basic python library? – Dima Apr 25 '17 at 22:14
  • @Dima: it's a standard Unix tool, if you are on Linux or OS X it's installed by default. – Matteo Italia Apr 25 '17 at 22:15
  • To add to @MatteoItalia's comment, if you want sed (or grep for that matter) under windows you can install cygwin which gives you a Linux shell and various useful Linux commands. – TimGJ Apr 25 '17 at 22:19
  • I'd prefer to just use python because it doesn't seem like it'd be that hard to program. I was just wondering if configparser had a function I'm missing. – Dima Apr 25 '17 at 22:19
  • @TimGJ: personally I prefer GnuWin32, they are native ports of the coreutils and other stuff (unlike Cygwin, which actually provides a full POSIX emulation layer). – Matteo Italia Apr 25 '17 at 22:22
  • @Dima nowadays with dockerized and virtualized environments, developing on windows brings a lot of cool toys for the most basic linux container or VM. – fiacre Apr 26 '17 at 19:00
0

Maybe this can work:

lines = open("file").readlines()

n_lines = ["%s" % line for line in lines if line.strip()]

f = open("file", "w")
f.write("".join(n_lines))
f.close()

I use the list comprehension and create a new variable with the filter lines.

EDIT

If you can add a linebreak for each section, this maybe can work:

lines = open("file").readlines()

n_lines = ["\n%s" % line if "[Sect" in line else line for line in lines if line.strip()]

f = open("file", "w")
f.write("".join(n_lines).lstrip())
f.close()

EDIT 2:

I'm not sure... but

If your file is so large and the Python that you work is 3 version, maybe you can use this code for better performance:

def readfile(filepath): 
    with open(filepath, "r") as f: 
        for line in f:
            yield line

lines = readfile("file")

n_lines = ["\n%s" % line if "[Sect" in line else line for line in lines if line.strip()]

f = open("file", "w")
f.write("".join(n_lines).lstrip())
f.close()

Reference

Community
  • 1
  • 1
kip
  • 1,120
  • 7
  • 11
  • Why can't it be written without the %: n_lines = [line for line in lines if line.strip()] – Dima Apr 25 '17 at 22:52
  • Yes you can get the value of `line` without the `%` – kip Apr 25 '17 at 22:54
  • 1
    Works great. It'd be perfect if it left one blank line after each section, but I can imagine that'd be a bit more complex. Maybe if it replaced each "[" with "\n[" except the first "[" – Dima Apr 25 '17 at 22:56
  • I edited the question with another code that maybe can work with a linebreak in each section.... – kip Apr 25 '17 at 23:02
  • I removed the first linebreak with `lstrip()` in the `.write()`, you can test the code and confirm.. – kip Apr 25 '17 at 23:09
  • There's no need to use `readlines()` to read the entire file into memory at once since they can be iterated over a line-at-a-time: i.e. `f = open(...)`, `for line in f:`, `,,,`. – martineau Apr 25 '17 at 23:27
  • The better solution for a large file is this : `with open('file', 'r') as f: for line in f: print line` [link](http://stackoverflow.com/questions/17246260/python-readlines-usage-and-efficient-practice-for-reading) – kip Apr 25 '17 at 23:37