Decision
To answer the question: is there a good way to avoid this behavior , although it depends on your courtesy value. Essentially, you need to wrap the numpy.savetxt function in another function or just use the code snippet shown here where you need to.
What I did was mix part of @mgilson code with the code provided in an answer to another similar question. In short, the code, a numpy.savetxt file using numpy.savetxt and excluding the last line, will be as follows:
import os with open('some_array.txt', 'w') as fout: NEWLINE_SIZE_IN_BYTES = 1
The definitions of os.SEEK_END and os.SEEK_SET can be found here . Although there are only 2 and 0, respectively.
Code logic
Some things to note here:
The file opens in text mode, not binary mode . This is important because writing and reading from a file in text mode is platform dependent unless you specify an encoding (which we usually don’t do, as in the two answers to this question). For example, a newline character reads differently on Windows or Linux. From the documentation :
Typically, files are opened in text mode, that is, you read and write lines from and to a file that are encoded in a specific encoding. If no encoding is specified, the platform is used by default (see Open () ). (...)
(...) In text mode, reading by default uses the conversion of platform-specific line endings ( \n on Unix, \r\n on Windows) to \n . When recording in text mode, by default, the occurrences are converted \n back to platform-specific line endings.
In the next line of code, fout.seek(0, os.SEEK_END) , we set the current file position to the end of the file (see Link for seek () ). This is the only valid operation from the end of the file in text mode, as I will quote later in this text.
- Then in the line
fout.seek(fout.tell() - NEWLINE_SIZE_IN_BYTES, os.SEEK_SET) we just tell Python:- Set the current position back 1 byte from the current position:
fout.tell() - NEWLINE_SIZE_IN_BYTES . Where tell() just returns the current position, as you can see in the link . - Starting at the beginning of the
os.SEEK_SET file.
- The reason this is done this way is that only the offsets returned by the
tell() function are allowed in the seek() method, as the seek() documentation says:If the file is opened in text mode (without ' b ), only offsets returned by the tell() function are allowed. Using other offsets causes undefined behavior.
- Finally, as it may now be obvious, the
truncate() method truncate() file only to its current position.
Another way in binary mode
I have to say that now I am not quite sure whether it is better to do this in text mode than in binary, although other answers made me think so, see Another question .
After the @mgilson code, we just need to open the file in binary mode. Modified Work Code:
NEWLINE_SIZE_IN_BYTES = -1
Both of these methods work for me in versions of Python> 3.2 .
César Arroyo Cárdenas
source share