straumle
straumle

Reputation: 135

python: Open file, edit one line, save it as the same file

I want to open a file, search for a specific word, change the word and save the file again. Sounds really easy - but I just can't get it working... I know that I have to overwrite the whole file but only change this one word!

My Code:

f = open('./myfile', 'r')
linelist = f.readlines()
f.close

for line in linelist:
    i =0;
    if 'word' in line:
        for number in arange(0,1,0.1)):
            myNumber = 2 - number
            myNumberasString = str(myNumber)

            myChangedLine = line.replace('word', myNumberasString)


            f2 = open('./myfile', 'w')
            f2.write(line)
            f2.close

            #here I have to do some stuff with these files so there is a reason
            #why everything is in this for loop. And I know that it will
            #overwrite the file every loop and that is good so. I want that :)

If I make it like this, the 'new' myfile file contains only the changed line. But I want the whole file with the changed line... Can anyone help me?

****EDIT*****

I fixed it! I just turned the loops around and now it works perfectly like this:

f=open('myfile','r')
text = f.readlines()
f.close()

i =0;
for number in arange(0,1,0.1):
    fw=open('mynewfile', 'w')

    myNumber = 2 - number
    myNumberasString = str(myNumber)
    for line in text:

        if 'word' in line:
            line = line.replace('word', myNumberasString)

        fw.write(line)
    fw.close()
    #do my stuff here where I need all these input files

Upvotes: 8

Views: 33852

Answers (3)

Padraic Cunningham
Padraic Cunningham

Reputation: 180411

Use fileinput passing in whatever you want to replace:

import  fileinput
for line in fileinput.input("in.txt",inplace=True):
    print(line.replace("whatever","foo"),end="")

You don't seem to be doing anything special in your loop that cannot be calculated first outside the loop, so create the string you want to replace the word with and pass it to replace.

inplace=True will mean the original file is changed. If you want to verify everything looks ok then remove the inplace=True for the first run and you will actually see the replaced output instead of the lines being written to the file.

If you want to write to a temporary file, you can use a NamedTemporaryFile with shutil.move:

from tempfile import NamedTemporaryFile
from shutil import move

with open("in.txt") as f, NamedTemporaryFile(dir=".",delete=False) as out:
    for line in f:
        out.write(line.replace("whatever","foo"))

move("in.txt",out.name)

One problem you may encounter is matching substrings with replace so if you know the word is always followed in the middle of a sentence surrounded by whitespace you could add that but if not you will need to split and check every word.

from tempfile import NamedTemporaryFile
from shutil import move
from string import punctuation
with open("in.txt") as f, NamedTemporaryFile(dir=".",delete=False) as out:
    for line in f:
        out.write(" ".join(word if word.strip(punctuation) != "whatever" else "foo" 
                 for word in line.split()))

Upvotes: 5

Max Spencer
Max Spencer

Reputation: 1719

You just need to write out all the other lines as you go. As I said in my comment, I don't know what you are really trying to do with your replace, but here's a slightly simplified version in which we're just replacing all occurrences of 'word' with 'new':

f = open('./myfile', 'r')
linelist = f.readlines()
f.close

# Re-open file here
f2 = open('./myfile', 'w')
for line in linelist:
    line = line.replace('word', 'new')
    f2.write(line)
f2.close()

Or using contexts:

with open('./myfile', 'r') as f:
    lines = f.readlines()

with open('./myfile', 'w') as f:
    for line in lines:
        line = line.replace('word', 'new')
        f.write(line)

Upvotes: 7

ODiogoSilva
ODiogoSilva

Reputation: 2414

The are three issues with your current code. First, create the f2 file handle before starting the loop, otherwise you'll overwrite the file in each iteration. Third, you are writing an unmodified line in f2.write(line). I guess you meant f2.write(myChangedLine)? Third, you should add an else statement that writes unmodified lines to the file. So:

f = open('./myfile', 'r')
linelist = f.readlines()
f.close
f2 = open('./myfile', 'w')

for line in linelist:
    i =0;
    if 'word' in line:
        for number in arange(0,1,0.1)):
            myNumber = 2 - number
            myNumberasString = str(myNumber)

            myChangedLine = line.replace('word', myNumberasString)

            f2.write(myChangedLine)
    else:
        f2.write(line)

f2.close()

Upvotes: 1

Related Questions