Prepend a line to an existing file in Python

PythonPrepend

Python Problem Overview


I need to add a single line to the first line of a text file and it looks like the only options available to me are more lines of code than I would expect from python. Something like this:

f = open('filename','r')
temp = f.read()
f.close()

f = open('filename', 'w')
f.write("#testfirstline")

f.write(temp)
f.close()

Is there no easier way? Additionally, I see this two-handle example more often than opening a single handle for reading and writing ('r+') - why is that?

Python Solutions


Solution 1 - Python

Python makes a lot of things easy and contains libraries and wrappers for a lot of common operations, but the goal is not to hide fundamental truths.

The fundamental truth you are encountering here is that you generally can't prepend data to an existing flat structure without rewriting the entire structure. This is true regardless of language.

There are ways to save a filehandle or make your code less readable, many of which are provided in other answers, but none change the fundamental operation: You must read in the existing file, then write out the data you want to prepend, followed by the existing data you read in.

By all means save yourself the filehandle, but don't go looking to pack this operation into as few lines of code as possible. In fact, never go looking for the fewest lines of code -- that's obfuscation, not programming.

Solution 2 - Python

I would stick with separate reads and writes, but we certainly can express each more concisely:

Python2:

with file('filename', 'r') as original: data = original.read()
with file('filename', 'w') as modified: modified.write("new first line\n" + data)

Python3:

with open('filename', 'r') as original: data = original.read()
with open('filename', 'w') as modified: modified.write("new first line\n" + data)

Note: file() function is not available in python3.

Solution 3 - Python

Other approach:

with open("infile") as f1:
    with open("outfile", "w") as f2:
        f2.write("#test firstline")
        for line in f1:
            f2.write(line)

or a one liner:

open("outfile", "w").write("#test firstline\n" + open("infile").read())

Thanks for the opportunity to think about this problem :)

Cheers

Solution 4 - Python

with open("file", "r+") as f: s = f.read(); f.seek(0); f.write("prepend\n" + s)

Solution 5 - Python

You can save one write call with this:

f.write('#testfirstline\n' + temp)

When using 'r+', you would have to rewind the file after reading and before writing.

Solution 6 - Python

Here's a 3 liner that I think is clear and flexible. It uses the list.insert function, so if you truly want to prepend to the file use l.insert(0, 'insert_str'). When I actually did this for a Python Module I am developing, I used l.insert(1, 'insert_str') because I wanted to skip the '# -- coding: utf-8 --' string at line 0. Here is the code.

f = open(file_path, 'r'); s = f.read(); f.close()
l = s.splitlines(); l.insert(0, 'insert_str'); s = '\n'.join(l)
f = open(file_path, 'w'); f.write(s); f.close()

Solution 7 - Python

This does the job without reading the whole file into memory, though it may not work on Windows

def prepend_line(path, line):
    with open(path, 'r') as old:
        os.unlink(path)
        with open(path, 'w') as new:
            new.write(str(line) + "\n")
            shutil.copyfileobj(old, new)

Solution 8 - Python

One possibility is the following:

import os
open('tempfile', 'w').write('#testfirstline\n' + open('filename', 'r').read())
os.rename('tempfile', 'filename')

Solution 9 - Python

If you wish to prepend in the file after a specific text then you can use the function below.

def prepend_text(file, text, after=None):
    ''' Prepend file with given raw text '''
    f_read = open(file, 'r')
    buff = f_read.read()
    f_read.close()
    f_write = open(file, 'w')
    inject_pos = 0
    if after:
        pattern = after
        inject_pos = buff.find(pattern)+len(pattern)
    f_write.write(buff[:inject_pos] + text + buff[inject_pos:])
    f_write.close()

So first you open the file, read it and save it all into one string. Then we try to find the character number in the string where the injection will happen. Then with a single write and some smart indexing of the string we can rewrite the whole file including the injected text now.

Solution 10 - Python

Am I not seeing something or couldn't we just use a buffer large-enough to read-in the input file in parts (instead of the whole content) and with this buffer traverse the file while it is open and keep exchanging file<->buffer contents?

This seems much more efficient (for big files especially) than reading the whole content in memory, modifying it in memory and writing it back to the same file or (even worse) a different one. Sorry that now I don't have time to implement a sample snippet, I'll get back to this later, but maybe you get the idea.

Solution 11 - Python

As I suggested in this answer, you can do it using the following:

def prepend_text(filename: Union[str, Path], text: str):
    with fileinput.input(filename, inplace=True) as file:
        for line in file:
            if file.isfirstline():
                print(text)
            print(line, end="")

Solution 12 - Python

If you rewrite it like this:

with open('filename') as f:
    read_data = f.read()
with open('filename', 'w') as f:
    f.write("#testfirstline\n" + read_data)

It's rather short and simple. For 'r+' the file needs to exist already.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNickView Question on Stackoverflow
Solution 1 - PythonNicholas KnightView Answer on Stackoverflow
Solution 2 - PythonKarl KnechtelView Answer on Stackoverflow
Solution 3 - PythonMorlockView Answer on Stackoverflow
Solution 4 - Pythonbarti_dduView Answer on Stackoverflow
Solution 5 - PythoninfraredView Answer on Stackoverflow
Solution 6 - PythonLove and peace - Joe CodeswellView Answer on Stackoverflow
Solution 7 - PythoneugView Answer on Stackoverflow
Solution 8 - PythonJooMingView Answer on Stackoverflow
Solution 9 - PythonPithikosView Answer on Stackoverflow
Solution 10 - PythonZuzu CorneliuView Answer on Stackoverflow
Solution 11 - PythonJD SolankiView Answer on Stackoverflow
Solution 12 - PythonSpartanView Answer on Stackoverflow