This is because truncation does not change the position of the stream.
When you read() file, you move the position to the end. Thus, sequential write will write to the file from this position. However, when you call flush() , it seems that it not only tries to write the buffer to the file, but also performs some error checking and corrects the current position of the file. When Flush() is called after truncate(0) , it does not write anything (the buffer is empty), then checks the file size and places the position in the first appropriate place (which is 0 ).
UPDATE
The Python file function is NOT just a wrapper around the equivalents of the standard C library, but knowing the C functions helps you know what is happening more accurately.
From the ftruncate man page :
The value of the search pointer does not change when the ftruncate () function is called.
From the fflush man page :
If a stream indicates an input stream or an update stream in which the most recent operation was entered, this stream is discarded if it is searchable and is not yet at the end of the file. Cleaning the input stream discards any buffered input and adjusts the file pointer so that the next input operation accesses the byte after the last read.
This means that if you put flush before truncate it will have no effect. I checked, and it was.
But to install flush after truncate :
If the stream indicates an output stream or an update stream in which the most recent operation has not been entered, fflush () forces writing any unwritten data for this stream to a file, and the st_ctime and st_mtime fields of the main file are marked for updating.
The man page does not mention the search pointer when explaining output streams when the last operation was not entered. (Here is our last truncate operation)
UPDATE 2
I found something in the source code of Python-3.2.2\Modules\_io\fileio.c:837 : Python-3.2.2\Modules\_io\fileio.c:837
#ifdef HAVE_FTRUNCATE static PyObject * fileio_truncate(fileio *self, PyObject *args) { PyObject *posobj = NULL; #ifndef MS_WINDOWS Py_off_t pos; #endif ... #ifdef MS_WINDOWS { PyObject *oldposobj, *tempposobj; HANDLE hFile;
Look at the two lines that I pointed out ( /////This Line///// ). If your platform is Windows, then it saves the position and returns it after truncation.
To my surprise, most of the flush functions inside Python 3.2.2 functions either did nothing or did not call the fflush C function at fflush . The truncated part of 3.2.2 was also very undocumented. However, I found something interesting in Python 2.7.2 sources. First I found this in Python-2.7.2\Objects\fileobject.c:812 in the truncate implementation:
To summarize, I think this is completely platform dependent. I checked the default Python 3.2.2 for Windows x64 and got the same results as you. I donβt know what is happening on * nixes.