8

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
12
  • 2
    You're truncating the whole file with 'w' mode, and only writing out the one line; what did you expect? Commented May 11, 2015 at 14:14
  • 1
    ok if you write it like that I could not have expected something different. but that's the only solution to write a file that I found... That's why I posted this question. How can I do it then? Commented May 11, 2015 at 14:15
  • 2
    @Cheng the OP wants to replace the line in-place, not necessarily append. Commented May 11, 2015 at 14:19
  • @Cheng: but I don't want to add it to the end of the document. The lines must resist in their order and only this one word must change... Commented May 11, 2015 at 14:19
  • @straumle: What are you trying to do with the inner for loop, you're just going to replace 'word' with '2' on the first iteration and then not do anything else as far as I can tell? Commented May 11, 2015 at 14:20

3 Answers 3

7

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)
Sign up to request clarification or add additional context in comments.

2 Comments

Hi Max. Hmm.... ok but that does not work either. It just replaces the whole document with the new lines. But I want to replace only the line and all other lines of the file must stay the same...
I've tested it and it seems to work as expected for me. If I create a file with several lines, some of them containing the string 'word', then after running either of the above programs the file still contains the same number of lines, just with all occurrences of 'word' changed to 'new'.
6

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()))

4 Comments

hmm... that does not work either. Then it just overwrites the whole document with this one line...
@straumle, the only way that happens is if the word you are replacing is your whole file
It's important to know that setting the inplace option on FileInput will temporarily take over the current stdout of the script which may or may not work depending on your use case. It may make more sense to read/write files using the open function unless this is just a simple utility script.
This only replaces whatever with foo if whatever appears in the line, if there is no whatever in the line the original line is written as is.
1

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()

1 Comment

Hi, thanks for your answer. I want to overwrite the file in each iteration :) And if I do it like this, it will just add the line at the end of the textfile. but that's not what I want. I want to replace the word in the existing file so that it looks exactly the same with exception of this one word...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.