Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

python

io

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
like image 504
straumle Avatar asked May 11 '15 14:05

straumle


3 Answers

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)
like image 74
Max Spencer Avatar answered Nov 04 '22 21:11

Max Spencer


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()))
like image 45
Padraic Cunningham Avatar answered Nov 04 '22 21:11

Padraic Cunningham


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()
like image 24
ODiogoSilva Avatar answered Nov 04 '22 20:11

ODiogoSilva