1

I imagine this is a question asked already twenty thousand times, but I cannot understand why the file is always empty. I want to open a file, remove a string from the whole file and then rewrite the content, but the file ends up being empty. This is the code I use:

f = open(filename,'w+')
f.write(f.read().replace(str_to_del,""))
f.close()

But the file is always empty. If I instead use "r+" then the content is appended and I have a duplicate text in the file. I'm using Python 3.3 . What am I missing?

LowFieldTheory
  • 1,722
  • 1
  • 26
  • 39
  • At the risk of looking very daft, aren't you replacing everything with an empty string? – Mike P Aug 04 '14 at 09:25
  • Yes, in fact. w+ empties the file, and I wonder why it works like that. f doesn't have the content of the file then, so what should I do? – LowFieldTheory Aug 04 '14 at 09:27
  • Short answer: open once in `'r'` to get the content, open again in `'w'` to replace the existing content. – jonrsharpe Aug 04 '14 at 09:27
  • @Novalink: If you don't know why `w+` mode is emptying the file, read the documentation on the [`open`](https://docs.python.org/3/library/functions.html#open) function (or `help(open)` in an interactive session; it will explain what the modes mean. – abarnert Aug 04 '14 at 09:28
  • [Getting atomic writes right](http://stupidpythonideas.blogspot.com/2014/07/getting-atomic-writes-right.html) may help you here. There are also libraries that can help; e.g., the `fatomic` referred to in that post lets you transform a file line-by-line, chunk-by-chunk, or whole-file-at-a-time without having to worry about the open, read, and write calls. (There are probably more robust and well-tested libraries than that one, I just happen to know that one because I wrote it and have used it a couple times; SO isn't a good place to find the best library, just a decent place for examples…) – abarnert Aug 04 '14 at 09:34
  • @jonrsharpe I'm sorry that I made a duplicated question, but really I couldn't find anything (finding that post would have been useful, yes). – LowFieldTheory Aug 04 '14 at 09:35
  • @abarnert the documentation doesn't show what w+ means, or I cannot get that piece of docs, because I can find only https://docs.python.org/3.4/tutorial/inputoutput.html where w+ isn't explained. – LowFieldTheory Aug 04 '14 at 09:35
  • 2
    @Novalink that's just the tutorial, you want the library reference: https://docs.python.org/3.4/library/functions.html#open – jonrsharpe Aug 04 '14 at 09:36
  • @Novalink: I linked to the docs in my comment. Just click on `open` in my previous comment. (Or follow jonrsharpe's link, which is more obvious.) – abarnert Aug 04 '14 at 10:02
  • Thanks, that's helpful :) – LowFieldTheory Aug 04 '14 at 13:11

1 Answers1

3

Opening the file in w+ mode truncates the file. So, your f.read() is guaranteed to return nothing.

You can do this by opening the file in r+ mode, reading it, then calling f.seek(0), then writing. Or by opening the file in r mode, reading it, closing it, reopening it in w mode, and writing. Or, better, by writing a temporary file and moving it over the original (which gives you "atomic" behavior—no possibility of ending up with a half-written file).

abarnert
  • 354,177
  • 51
  • 601
  • 671
  • Now I have put f.seek(0) as you said but I have some junk lines in the end every time - instead of having 50 lines before and after, I have then 60 lines.. I don't understand – LowFieldTheory Aug 04 '14 at 13:18
  • @Novalink: When you seek to 0 in a file that's, say, 12000 bytes long, then write 10000 bytes, that overwrites the first 10000 bytes of the file, and leaves the other 2000 behind. You can fix that by using `f.truncate()` after you're done writing. But again, it would be better to write to a temporary file and move it over the original, instead of trying to modify the existing file in-place. – abarnert Aug 05 '14 at 03:29
  • the bytes rewritten are the same – LowFieldTheory Aug 05 '14 at 15:33
  • @Novalink: In the example you gave us, you're replacing each occurrence of some non-empty string with the empty string, which means there can't _possibly_ be the same number of bytes. If you have a different example that's working differently, give us an MCVE and we can debug that one. – abarnert Aug 05 '14 at 21:58
  • Sorry, I forgot - later a number is replaced but initially some strings are deleted. Anyway in the while I solved with a " open(filename,'w+') " among the read and write (how to format code in comments? – LowFieldTheory Aug 06 '14 at 06:40
  • @Novalink: You can't format code in comments. Often the code really should be part of your original question; if so, just edit the question. (Don't edit to make it ask something different than you originally asked; do edit to make it ask the same thing more clearly.) If not, the best option is to post it somewhere like http://pastebin.com and post a link in a question. – abarnert Aug 06 '14 at 17:04
  • @Novalink: Anyway, I don't understand your comment, but if you're still having problems, can I recommend for a third time that you write a temporary file and overwrite instead of trying to write the same file that you have open? It makes all of your problems go away, it means you don't lose any data if your program halts mid-stream, it's just generally better in every way for 90% of all programs. – abarnert Aug 06 '14 at 17:06
  • I already solved all my problems, thanks :) I wanted to know how to evidence it with grey like you did above with "f.truncate()" – LowFieldTheory Aug 06 '14 at 22:15