Question: I have this very simple Python program: def print_file(filename): with open(filename,'r') as read_file: print(read_file.read()) def create_random_file(filename,count): with open(filename,'w+', encoding='utf-8') as writefile: for row_num in range(count): writefile.write(f'{row_num}: fo bar baz\n') def truncate_file_after_first_line(file,read_a_line): file.seek(0,0) # go to start of file print(f"After seeking to 0, at position {file.tell()}"); if (read_a_line): header = file.readline() print(f"After reading a line, at position {file.tell()}"); print(f"Found header '{header.rstrip()}'\n") file.write('TRUNCATE AFTER THIS\n') print(f"After writing marker, at position {file.tell()}"); file.truncate() def mangle_file(filename,read_a_line): with open(filename,'r+') as file: truncate_file_after_first_line(file,read_a_line) # ---- filename = 'testpy.txt' read_a_line = True create_random_file(filename,5) print("Original file:") print_file(filename) mangle_file(filename,read_a_line) print("Truncated file:") print_file(filename)  So, I:  I create a file with 5 lines (and print it to stdout too). Then, in mangle_file():  I open the file with the r+ option, i.e. Open for reading and writing. The stream is positioned at the beginning of the file. Depending on bool read_a_line, I then either  a) Seek to position 0, read a line, write the marker TRUNCATE AFTER THIS\n, then truncate the file. b) Seek to position 0, write the marker TRUNCATE AFTER THIS\n, then truncate the file.   Finally I close the file   And then re-read it to print it.  Sounds straightforward but for a) where the first line in the file (i.e. 0: fo bar baz) is read before truncation, the resulting file is: 0: fo bar baz 1: fo bar baz 2: fo bar baz 3: fo bar baz 4: fo bar baz TRUNCATE AFTER THIS  i.e. the truncate() did nothing, the marker has been appened to the untruncated file. Whereas I would expect truncation after the first line read: 0: fo bar baz TRUNCATE AFTER THIS  For b), as expected, the resulting file is TRUNCATE AFTER THIS  What do I get wrong about truncate()? Update: Added some tells With read_a_line = True Original file: 0: fo bar baz 1: fo bar baz 2: fo bar baz 3: fo bar baz 4: fo bar baz After seeking to 0, at position 0 After reading a line, at position 14 Found header '0: fo bar baz' After writing marker, at position 90 Truncated file: 0: fo bar baz 1: fo bar baz 2: fo bar baz 3: fo bar baz 4: fo bar baz TRUNCATE AFTER THIS  With read_a_line = False Original file: 0: fo bar baz 1: fo bar baz 2: fo bar baz 3: fo bar baz 4: fo bar baz After seeking to 0, at position 0 After writing marker, at position 20 Truncated file: TRUNCATE AFTER THIS 

Answer: From the fopen documentation:  Reads and writes may be intermixed on read/write streams in any order. Note that ANSI C requires that a file positioning function intervene between output and input, unless an input operation encounters end-of-file. (If this condition is not met, then a read is allowed to return the result of writes other than the most recent.) Therefore it is good practice (and indeed sometimes necessary under Linux) to put an fseek(3) or fsetpos(3) operation between write and read operations on such a stream. This operation may be an apparent no-op (as in fseek(..., 0L, SEEK_CUR) called for its synchronizing side effect).  If you change  file.write('TRUNCATE AFTER THIS\n')  to  file.seek(file.tell()) file.write('TRUNCATE AFTER THIS\n')  the function should behave as you intended (it does on my MacOS). Otherwise, "r+" may behave as if the mode was like "ra" (even though that is not a valid mode) -- that is, only appending later in the file or at the very end (depending on how much text was already buffered).