Why is the correct position of the current position for files not truncated properly?

In the answer to another question, there was a strange behavior typical of Python 3. for the truncate command (focus):

Resize the stream to the specified size in bytes (or the current position if no size is specified) . The current position of the stream does not change. This resizing may extend or reduce the current file size. In the case of expansion, the contents of the new file area depend on the platform (in most systems, additional bytes are filled with zeros). The new file size is returned.

But...

 >>> open('temp.txt', 'w').write('ABCDE\nFGHIJ\nKLMNO\nPQRST\nUVWXY\nZ\n') 32 >>> f = open('temp.txt', 'r+') >>> f.readline() 'ABCDE\n' >>> f.tell() 6 # As expected, current position is 6 after the readline >>> f.truncate() 32 # ?! 

Instead of truncating at the current position (6), it is truncated at the end of the file (i.e. not at all). This was verified by checking the file on disk.

This process works as expected (the file is truncated to 6 bytes) in Python 2 as well as in Python 3, using StringIO instead of the file. Why doesn't this work as expected with files in Python 3? This is mistake?

(Edit: it also works correctly if explicit f.seek(6) given immediately before truncate .)

+5
source share
2 answers
 >>> open('temp.txt', 'w').write('ABCDE\nFGHIJ\nKLMNO\nPQRST\nUVWXY\nZ\n') 32 >>> f = open('temp.txt', 'r+') >>> f.readline() 'ABCDE\n' >>> f.seek(6) >>> f.truncate() 

This fixes the problem, if nothing else, why this happens, I have no idea, but it would be nice to report this upstream, if it was not already.

These are the only textual differences from truncate() functions between Python3 and Python2 that I could find (with the exception of related function calls inside the truncate function itself):

 33,34c33,34 < except AttributeError as err: < raise TypeError("an integer is required") from err --- > except AttributeError: > raise TypeError("an integer is required") 54c54 < """Truncate size to pos, where pos is an int.""" --- > """Truncate size to pos.""" 

I am sure that someone pats my fingers on the subject, but I think that it is more connected with flush() calls and how the buffer is processed after a flash call. Almost as if he had not reset to the previous position after flushing all the inputs / outputs. this is a wild assumption in which there is no technical means to support it, but that would be my first assumption.

Checked in flush() situation, here is the only difference between them, of which Python2 performs the following operation, which Python3 does not do (even the source code is not enough for it):

 def _flush_unlocked(self): if self.closed: raise ValueError("flush of closed file") while self._write_buf: try: n = self.raw.write(self._write_buf) except BlockingIOError: raise RuntimeError("self.raw should implement RawIOBase: it " "should not raise BlockingIOError") except IOError as e: if e.errno != EINTR: raise continue if n is None: raise BlockingIOError( errno.EAGAIN, "write could not complete without blocking", 0) if n > len(self._write_buf) or n < 0: raise IOError("write() returned incorrect number of bytes") del self._write_buf[:n] 

This is a BufferedWriter function that appears to be used in this I / O operation.
Now I'm late for a date, so please think it will be interesting to see what you guys find in the mean time!

+3
source

I discovered a problem to track Python issues, and the answer seems to be related to buffering:

 >>> open('temp.txt', 'w').write('ABCDE\nFGHIJ\nKLMNO\nPQRST\nUVWXY\nZ\n') 32 >>> f = open('temp.txt', 'r+') >>> f.readline() 'ABCDE\n' >>> f.tell() 6 >>> f.buffer.tell() 32 

For some reason, truncate works with a buffer position rather than a top-level position. Actually, this is not limited to truncate and produces other unexpected results, for example:

 >>> open('temp.txt', 'w').write('ABCDE\nFGHIJ\nKLMNO\nPQRST\nUVWXY\nZ\n') 32 >>> f = open('temp.txt', 'r+') >>> f.readline() 'ABCDE\n' >>> f.write('test') 4 >>> f.close() >>> open('temp.txt').read() 'ABCDE\nFGHIJ\nKLMNO\nPQRST\nUVWXY\nZ\ntest' 

The developer stated that there is a problem, although I am not quite sure in his statement what the problem is. However, it appears flagged for correction.

+2
source

Source: https://habr.com/ru/post/1240922/


All Articles