366

Is there a way to open a file for both reading and writing?

As a workaround, I open the file for writing, close it, then open it again for reading. But is there a way to open a file for both reading and writing?

Aran-Fey
  • 39,665
  • 11
  • 104
  • 149
bigredhat
  • 3,669
  • 2
  • 15
  • 3
  • 3
    what problem you are solving? maybe there is a better solution than writing/reading a file, e.g. `mmap` – Roman Bodnarchuk Jul 11 '11 at 10:08
  • 1
    Could you give us your code so we will be able to answer you. You can also try to take a look: http://docs.python.org/tutorial/inputoutput.html#reading-and-writing-files . However i have tried to use r+b and it works. Also is there any benefit to use one file descriptor in diff functions? – Artsiom Rudzenka Jul 11 '11 at 10:09
  • @RomanBodnarchuk `mmap` is a great idea, but what if you have to deal with concurrency? Is there a way to reserve access? – Dr_Zaszuś Feb 20 '20 at 14:27

4 Answers4

429

Here's how you read a file, and then write to it (overwriting any existing data), without closing and reopening:

with open(filename, "r+") as f:
    data = f.read()
    f.seek(0)
    f.write(output)
    f.truncate()
Flimm
  • 136,138
  • 45
  • 251
  • 267
  • 70
    use `a+` to cover end-case that the file does not exist (will be created) – Jossef Harush Kadouri Oct 21 '15 at 19:26
  • 35
    seek() and truncate() are both critical! – smwikipedia Feb 17 '16 at 09:49
  • @Flimm adding len(data) to seek, reads and appends a new string, but it also seems to remove the last character of the text file. – multigoodverse May 01 '16 at 10:41
  • I just opened a new question regarding reading and appending: http://stackoverflow.com/questions/36965852/how-do-i-read-and-append-to-text-file-in-one-pass – multigoodverse May 01 '16 at 10:58
  • It doesn't seem like 'r+' overwrites the file, but rather appends. Is there a way to have to overwrite? – Lithimlin May 01 '18 at 15:50
  • 1
    @Lithimlin `r+` allows both reads and writes. You can overwrite the file by following the instructions in the answer. – Flimm May 01 '18 at 19:56
  • 16
    @JossefHarush Note that the documentation for `a` states 'on some Unix systems, means that all writes append to the end of the file regardless of the current seek position'. In this case the `f.seek(0)` won't work as expected. I just fell foul of this on Linux. – Graeme Jun 25 '18 at 16:02
  • @Graeme - great input, haven't bumped into this behavior. what solved your case? `r+`? – Jossef Harush Kadouri Jun 26 '18 at 06:17
  • @JossefHarush Plain `open()` isn't enough if it might not exist. You need to an `fd=os.open(..., os.O_RDWR|os.O_CREAT)` to ensure creation, then `os.fdopen(fd, 'r+')`. See https://stackoverflow.com/a/10352231/2801913 – Graeme Jun 26 '18 at 19:05
  • 25
    It's better you explain why `seek` and `truncate` is used here. Most of the readers come from google and do copy-paste. – Shiplu Mokaddim Mar 13 '19 at 10:58
  • 44
    After you have read the file, the file pointer(fp) has moved forward, so you need to set it to the beginning. That's that `seek(0)` does: it places the fp to position `0` (*i.e.* the beginning). `truncate()` truncate the file to the provided number of bytes, *i.e.* removes all of the file content after the specified number of bytes. Imagine that your file has the string `Hello, world` and you write `Bye`. If you don't `truncate()` the content at the end will be `Byelo, world`, since you never deleted the text that existed in the file. `truncate()` truncates the file to the current fp. – Illya Gerasymchuk Jul 14 '19 at 12:18
  • 7
    Is this faster than first open for just reading 'r', close, and then open for wrtiting 'w'? – Dr_Zaszuś Feb 20 '20 at 14:25
  • Could we use `w+` as well? – alper Apr 02 '22 at 13:26
  • 1
    @alper No, you can't use `w+` as this truncates file as part of opening so reading it is not possible as there is no content anymore. – Piotr Dobrogost Jul 31 '22 at 10:57
322

Summarize the I/O behaviors:

Mode r r+ w w+ a a+
Read + + + +
Write + + + + +
Create + + + +
Cover + +
Point in the beginning + + + +
Point in the end + +

Decision tree for the table above:

BSMP
  • 4,596
  • 8
  • 33
  • 44
AbstProcDo
  • 19,953
  • 19
  • 81
  • 138
52

r+ is the canonical mode for reading and writing at the same time. This is not different from using the fopen() system call since file() / open() is just a tiny wrapper around this operating system call.

Delgan
  • 18,571
  • 11
  • 90
  • 141
25

I have tried something like this and it works as expected:

f = open("c:\\log.log", 'r+b')
f.write("\x5F\x9D\x3E")
f.read(100)
f.close()

Where:

f.read(size) - To read a file’s contents, call f.read(size), which reads some quantity of data and returns it as a string.

And:

f.write(string) writes the contents of string to the file, returning None.

Also if you open Python tutorial about reading and writing files you will find that:

'r+' opens the file for both reading and writing.

On Windows, 'b' appended to the mode opens the file in binary mode, so there are also modes like 'rb', 'wb', and 'r+b'.

Artsiom Rudzenka
  • 27,895
  • 4
  • 34
  • 52
  • 7
    Also reading then writing works equally well using 'r+b' mode, but you have to use f.seek(0) between f.read() and f.write() to place the cursor back at the beginning of the file. – gaborous Nov 14 '12 at 18:05
  • 3
    Note that if the data you're writing isn't longer that the data already there, it will not get truncated. Use the `truncate` method to stop this. – Flimm Apr 12 '13 at 15:27