3
text = open('samiam.txt', 'r+')
keyword = " i "
keyword2 = "-i-"
replacement = " I "
replacement2 = "-I-"

for line in text:    
    if keyword in line:
        text.write(line.replace(keyword, replacement))
        print line
    elif keyword2 in line:
        text.write(line.replace(keyword2, replacement2))
        print line
    else:
        print line
text.close()

I'm not entirely sure why the text is not being written to the file. help?

Andrea
  • 73
  • 2
  • 2
  • 7
  • 1
    Could you show the sample of your file. – WannaBeCoder Dec 31 '14 at 06:46
  • i am Sam Sam i am That Sam-i-am! That Sam-i-am! i do not like that Sam-i-am! Do you like green eggs and ham? i do not like them, Sam-i-am. i do not like green eggs and ham. – Andrea Dec 31 '14 at 06:57
  • Maybe, you are not opening file in write or append mode – Ashwani Dec 31 '14 at 07:08
  • You do not write to the file, but you write to stdout. So why should it be written to the file? – glglgl Dec 31 '14 at 07:43
  • Your second set of substitutions is a non-sequitur, as `'i'`s are always replaced to `'I'`s before you have a chance to look at the second keyword. – gboffi Dec 31 '14 at 07:51
  • gboffi: "second set of substitutions" ...meaning what lines of code, exactly? – Andrea Dec 31 '14 at 08:08
  • glglgl - "but you write to stdout" ...what is stdout? – Andrea Dec 31 '14 at 08:11
  • Standard output is usually your terminal, but if you run with `python yourscript.py >output` then it is redirected to the file `output`. This is a feature of your shell / command interpreter, outside of Python. – tripleee Dec 31 '14 at 08:12
  • @gboffi: No, that is not true; the first substitution is not just `"i"` but `" i "` with spaces on both sides. – tripleee Dec 31 '14 at 08:14
  • @triplee You're correct! What do you think? do I need a new pair of glasses? My apologies to the OP for this misunderstanding of mine. – gboffi Dec 31 '14 at 08:20
  • 1
    @Andrea Never transcribe your code but rather copy and paste it... – gboffi Dec 31 '14 at 08:43

4 Answers4

2

In your code just replace the line

for line in text:

with

for line in text.readlines():

Note that here I am assuming that the you are trying to add the output at the end of the file. Once you have read the entire file, the file pointer is at the end of the file (even if you opened the file in r+ mode). Thus doing a write will actually write to the end of the file, after the current contents.

You can examine the file pointer by embedding text.tell() at different lines.

Here is another approach:

with open("file","r") as file: 
    text=file.readlines() 
i=0 
while i < len(text): 
    if keyword in text[i]: 
        text[i]=text[i].replace(keywork,replacement) 
with open("file","w") as file: 
    file.writelines(text)
Prakash Kuma
  • 722
  • 1
  • 6
  • 11
  • I'm not the one who downvoted you, but I did check this answer and it didn't appear to change anything. – Andrea Dec 31 '14 at 08:19
  • Actually it does change things, but the description of what it does is poor and it's probably not what you want. What he is trying to say, between the cursing and the poor formatting, is that you cannot write to the end of the file while you are in the middle of reading from it. The change fixes that, but ends up appending new output to the end of the file, not rewriting the file. – tripleee Dec 31 '14 at 08:21
  • I already mentioned that after reading the code i assumed that only. Also if u really wanna rewrite why don't u open the file save it in a list and after modification of the list write it back. The problem with the code was that after read the file the file pointer moved to the end and thus the rewriting the existing line is not possible unless u move the file pointer. – Prakash Kuma Dec 31 '14 at 08:26
  • And @tripleee as far as poor formatting is concerned, u can check that i have started since yesterday, still i am trying to be as accurate as possible. I really don't know what are the proper formatting rules and still learning. And Andrea I know u have not down voted and i was not pointing towards u, Since u don't have the required credits to downvote just like me. – Prakash Kuma Dec 31 '14 at 08:30
  • Yes, r+ both reads and writes to the file. But the problem is with file pointer i think. Check these links in case u have not seen them. http://stackoverflow.com/questions/14271216/beginner-python-reading-and-writing-to-the-same-file. http://bugs.python.org/issue3207 – Prakash Kuma Dec 31 '14 at 08:44
  • What i usually do is something like this. with open("file","r") as file: text=file.readlines() i=0 while i < len(text): if keyword in text[i]: text[i]=text[i].replace(keywork,replacement) with open("file","w") as file: file.writelines(text) – Prakash Kuma Dec 31 '14 at 08:50
1

It will be good to use two descriptors - one for reading and other for writing, for readability and single write operation.

text_read = open('samiam.py', 'r').read()
words_replacer_dict = {" i " : " I ", "-i-" : "-I-"}
replaced_text = ""

for line in text_read.split("\n"):
    for word, new_word in words_replacer_dict.items():
        replaced_text += line.replace(word, new_word)

text_read.close()
text_write = open('samiam.py', 'w')
text_write.write(replaced_text)
text_write.close()

You can even keep a count and write based on count, if you are bothered about memory in this case. Just open the file in read mode with generator expression and keep a reference count to satisfy write operation. NOTE: Read here(not an official link), to learn better about dictionary methods.

However, if you prefer to use read and write, always use seek operation to get to the line that is to be replaced and use flush once you finish writing the file. However, you cannot replace the line that is already there in the file through the seek and flush method. You can merely add something to the file. (eg)

text = open('samiam.py', 'r+')
count = 1
new_text = ""
for line in text:
    new_text += "%d:%s\n" % (count, line)
    count += 1
text.seek(0)
text.truncate()
text.write(new_text)
text.seek(0)
for line in text:
    print line
text.close()

For a better reading on why it is not possible to read and write to file like you wish, please see here

Community
  • 1
  • 1
thiruvenkadam
  • 4,170
  • 4
  • 27
  • 26
  • new_word is the value(such as " I ", "-I-") from the dictionary. – thiruvenkadam Dec 31 '14 at 08:22
  • "For a better reading on why..." The link says this: "Unfortunately there is no way to insert into the middle of a file without re-writing it" ...but I'm okay with re-writing it... I think. – Andrea Dec 31 '14 at 08:45
  • what does 'items' do at the end of dictionary? I looked it up but I still don't understand... – Andrea Dec 31 '14 at 09:11
  • items would give you the dictionary in the form of a list of two value tuples. Like {'a':1, 'b':2} => [('a',1), ('b', 2)] – thiruvenkadam Dec 31 '14 at 10:46
1

Use the fileinput module. (See also the MOTW site.)

import fileinput
keyword1 = " i "
keyword2 = "-i-"
replacement1 = " I "
replacement2 = "-I-"
for line in fileinput.input('your.file', inplace=True):
    line = line.rstrip()
    if keyword1 in line:
        line = line.replace(keyword1, replacement1)
    elif keyword2 in line:
        line = line.replace(keyword2, replacement2)
    print line

The fileinput module, when you use the inplace option, renames the input file and redirects stdout to a new file with the original file name

If you want to preserve the whitespace on the right of each line, don't rstrip and use print line, (note the final comma) to output the processed lines.

gboffi
  • 22,939
  • 8
  • 54
  • 85
  • what is "line.rstrip()" I understand the concept of stripping white spaces... but why is the 'r' in front of it? – Andrea Dec 31 '14 at 08:24
  • There are different functions for stripping from both sides, from the left, and from the right only. `rstrip` strips only from the right, i.e. from the end of the string. – tripleee Dec 31 '14 at 08:24
  • How much is it stripping? Let's say the line is "i do not like them, sam-i-am." ...what would that change? – Andrea Dec 31 '14 at 08:32
  • 'r' is for 'right'. Here we use `print` that adds a newline to what it prints, so if the `line` contains a newline character in the output file all the lines of text would be separated by a blank line. To avoid this behaviour, we strip all the whitespace on the right, on the assumption that left whitespace is significant (read 'indents are significant') while right whitespace can be sacrificed to have a proper formatting of the output. If you want to keep ALL the whitespace, don't `rstrip` and use `print line,` (with the final comma) so that a further newline is not appended. – gboffi Dec 31 '14 at 08:33
  • I have to say that apparently you don't know that every line you read from a file is terminated by a newline character... The line you're processing is not "i do not like them, sam-i-am." but rather it is "i do not like them, sam-i-am.\n", do you see the difference? – gboffi Dec 31 '14 at 08:37
0

It is because you are trying to read and write at the same time. Try something like:

# Read operation
lines = []
for line in text.readlines():
    if keyword in line:
        lines.append(line.replace(keyword, replacement))
        print line
    elif keyword2 in line:
        lines.append(line.replace(keyword2, replacement2))
        print line
    else:
        lines.append(line)
        print line
text.close()

# Write operation
text = open('dummy.py', 'w+')
text.writelines(lines)
text.close()

Bonus:

with open('data.txt') as f:
     data = f.read()

is more pythonic.

Prashanth
  • 1,252
  • 2
  • 13
  • 28