Undocumented file behaviour (mode='r+')

Syver Enstad syver-en+usenet at online.no
Mon Sep 9 23:35:02 CEST 2002


It would be nice for those of us who are not familiar with all the in's
and out's of file processing to include in the documentation for file
objects the behaviour of the write and read methods when opening a
file for updating ('r+' or 'rb+'). 

I finally understood what was happening when I looked up the MSDN C-runtime
library documentation for fopen. Before that I was pretty amazed that
my calls to write failed to have an impact on the file that it was
called on. Pretty that both write and read fails without notice
methinks, but when that is the behaviour of the underlying library I
understand it might be difficult to fix.

Here's the behaviour I am talking about:

class FileBugTestForWin2k(unittest.TestCase):
    """ Demonstrates that you have to do a
    flush after writing, if you are gonna read
    and a seek after reading if you are gonna write.

    It seems that the MS documentation is faulty, the unix man page
    documents the same behaviour as we're seeing here
    """
    def setUp(self):
        f1 = open('aTestingFile.bin', 'wb')
        f1.write('lots of shit')
        f1.close()

    def tearDown(self):
        import os
        os.unlink('aTestingFile.bin')

    def testFailureWithoutSeek(self):
        f2 = open('aTestingFile.bin', 'rb+')
        assert f2.read(2) == 'lo'
        f2.write('s') # here is the bug, nothing is written to the file
        f2.seek(0)
        # should have been 'loss of shit' but write fails silently
        self.assertEquals('lots of shit', f2.read())

    def testFailureWithFlush(self):
        """ This should be successful according to the docs
        """
        f2 = open('aTestingFile.bin', 'rb+')
        assert f2.read(2) == 'lo'
        f2.flush() # MS C-runtime docs say we have to flush or
                   # seek when switching from read to write
        self.assertRaises(IOError, f2.write, 's') # write fails here with
                                        # errno 0
    def testSuccessfulWithSeek(self):
        f2 = open('aTestingFile.bin', 'rb+')
        f2.read(2)
        f2.seek(2) # ATTENTION, I didn't know that you had to seek when
                   # switching between read and write operations on the file.
        f2.write('s')
        f2.seek(0)
        self.assertEquals('loss of shit', f2.read())

    def testWriteToReadFailure(self):
        f2 = open('aTestingFile.bin', 'rb+')
        f2.write('s')
        assert len(f2.read()) > 300 # reads a load of crap

    def testWriteToReadFailure(self):
        f2 = open('aTestingFile.bin', 'rb+')
        f2.write('s') # advancing file pointer 1 step into the file
        f2.flush()
        self.assertEquals('ots of shit', f2.read()) # reading from seek(1)


-- 

Vennlig hilsen 

Syver Enstad



More information about the Python-list mailing list