Mr_and_Mrs_D
Mr_and_Mrs_D

Reputation: 34086

Why calling file.read in python fills my file with garbage?

Running this:

import os

if __name__ == '__main__':
    exclude = os.path.join(
        r"C:\Dropbox\eclipse_workspaces\python\sync\.git", "info", "exclude")
    with open(exclude, 'w+') as excl:  # 'w' will truncate
        # print excl.read() # empty
        # excl.readall() # AttributeError: 'file' object has no attribute
        # 'readall' -- this also I do not understand
        excl.write('This will be written as expected if I comment the
         line below')
        print "Garbage\n\n", excl.read()
    # if I do not comment the line however, the file contains all the garbage
    # excl.read() just printed (edit: in addition to the line I wrote)

results in filling my file with garbage - why ? Also why readall is not resolved ?

Python 2.7.3

Latest iteration:

#!/usr/bin/env python2
import os

if __name__ == '__main__':
    exclude = os.path.join(r"C:\Users\MrD","exclude")
    with open(exclude,'w+') as excl:
        excl.write('This will be written if I comment the line below')
        print "Garbage\n\n",excl.read()
    # now the file contains all the garbage
    raw_input('Lol >')

Upvotes: 1

Views: 1751

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1124978

You have hit a pecularity in the way I/O is implemented at the C level. When you opened the file in + mode (write and read in your case), then you must issue a flush or seek before 'switching' modes, otherwise the behaviour is undefined. In this case, you added uninitialised memory to the file.

There is a report for this in the Python issue tracker: http://bugs.python.org/issue1394612

The work-around is to seek back to start if you wanted to read back what you have written:

with open(exclude,'w+') as excl:
    excl.write('This will be written if I comment the line below')
    excl.seek(0)
    print "No more garbage\n\n", excl.read()

You could use a flush too:

with open(exclude,'w+') as excl:
    excl.write('This will be written if I comment the line below')
    excl.flush()
    print "No more garbage, eof so empty:\n\n", excl.read()

Upvotes: 5

Related Questions