tags:

views:

10784

answers:

6

I'm using Python, and would like to insert a string into a text file without deleting or copying the file. How can I do that?

+3  A: 

Depends on what you want to do. To append you can open it with "a":

 with open("foo.txt", "a") as f:
     f.write("new line\n")

If you want to preprend something you have to read from the file first:

with open("foo.txt", "r+") as f:
     old = f.read() # read everything in the file
     f.seek(0) # rewind
     f.write("new line\n" + old) # write the new line before
Armin Ronacher
Just a small addition, to use the `with` statement in Python 2.5 you need to add "from __future__ import with_statement". Other than that, opening files with the `with` statement is definitely more readable and less error-prone than manual closing.
Alexander Kojevnikov
A: 

Do you want to append the text at the end of the file or insert it in the middle?

If append, just open the file in append mode:

f = open('spam.txt', 'a')
f.write('ham')
f.close()

If you want to insert, you open the file in write mode, then seek to the required position, and finally write to the file.

I suggest you check the official docs.

Alexander Kojevnikov
You can't insert. You can only overwrite stuff in the middle. Be careful.
S.Lott
+11  A: 

Unfortunately there is no way to insert into the middle of a file without re-writing it. As previous posters have indicated, you can append to a file or overwrite part of it using seek but if you want to add stuff at the beginning or the middle, you'll have to rewrite it.

This is an operating system thing, not a Python thing. It is the same in all languages.

What I usually do is read from the file, make the modifications and write it out to a new file called myfile.txt.tmp or something like that. This is better than reading the whole file into memory because the file may be too large for that. Once the temporary file is completed, I rename it the same as the original file.

This is a good, safe way to do it because if the file write crashes or aborts for any reason, you still have your untouched original file.

Sorry not to post example code, I'm a C++ guy and am only just learning Python. I'm sure the other overflowers here would laugh at my pathetic attempt!

Adam Pierce
"overflowers"? Stackers! :-) http://stackoverflow.com/questions/88947/what-should-visitors-to-stackoverflow-be-called
Ray Vega
Hey, I like "Stackers"!
Adam Pierce
+3  A: 

Rewriting a file in place is often done by saving the old copy with a modified name. Unix folks add a ~ to mark the old one. Windows folks do all kinds of things -- add .bak or .old -- or rename the file entirely or put the ~ on the front of the name.

import shutil
shutil.move( afile, afile+"~" )

destination= open( aFile, "w" )
source= open( aFile+"~", "r" )
for line in source:
    destination.write( line )
    if <some condition>:
        destination.write( >some additional line> + "\n" )
source.close()
destination.close()

Instead of shutil, you can use the following.

import os
os.rename( aFile, aFile+"~" )
S.Lott
+3  A: 

Python's mmap module will allow you to insert into a file. The following sample shows how it can be done in Unix (Windows mmap may be different). Note that this does not handle all error conditions and you might corrupt or lose the original file. Also, this won't handle unicode strings.

import os
from mmap import mmap

def insert(filename, str, pos):
    if len(str) < 1:
        # nothing to insert
        return

    f = open(filename, 'r+')
    m = mmap(f.fileno(), os.path.getsize(filename))
    origSize = m.size()

    # or this could be an error
    if pos > origSize:
        pos = origSize
    elif pos < 0:
        pos = 0

    m.resize(origSize + len(str))
    m[pos+len(str):] = m[pos:origSize]
    m[pos:pos+len(str)] = str
    m.close()
    f.close()

It is also possible to do this without mmap with files opened in 'r+' mode, but it is less convenient and less efficient as you'd have to read and temporarily store the contents of the file from the insertion position to EOF - which might be huge.

mhawke
+1  A: 

The fileinput module of the Python standard library will rewrite a file inplace if you use the inplace=1 parameter:

import sys
import fileinput

# replace all occurrences of 'sit' with 'SIT' and insert a line after the 5th
for i, line in enumerate(fileinput.input('lorem_ipsum.txt', inplace = 1)):
    sys.stdout.write(line.replace('sit', 'SIT'))  # replace 'sit' and write
    if i == 4: sys.stdout.write('\n')  # write a blank line after the 5th line
Dave