Numpy.savetxt () stop new line on last line

numpy.savetxt () seems to always put a new line at the end of files. Is there a good way to avoid this behavior? Substituting a new line character for something else does not help.

I do not think this applies to my code, but the recording is done like this (the model is a 3D array):

np.savetxt(modelFile, model, delimiter=",", fmt='%.3f') 
+9
python numpy
source share
2 answers

I'm not sure why this matters, or if there is a way to prevent it on the numpy side (I didn't see anything in the docs ...), but you can probably go back to the file after writing and then truncate. eg.

 NEWLINE_SIZE_IN_BYTES = -1 # -2 on Windows? with open('data.dat', 'w') as fout: np.savetxt(fout, model, delimiter=",", fmt='%.3f') fout.seek(NEWLINE_SIZE_IN_BYTES, 2) fout.truncate() 

Note: to search back, the byte size must be negative

+5
source share

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 # 2 on Windows? np.savetxt(fout, some_array) # Use np.savetxt. fout.seek(0, os.SEEK_END) # Go to the end of the file. # Go backwards one byte from the end of the file. fout.seek(fout.tell() - NEWLINE_SIZE_IN_BYTES, os.SEEK_SET) fout.truncate() # Truncate the file to this point. 

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 # -2 on Windows? with open('data.dat', 'wb') as fout: # Note 'wb' instead of 'w' np.savetxt(fout, model, delimiter=",", fmt='%.3f') fout.seek(NEWLINE_SIZE_IN_BYTES, 2) fout.truncate() 

Both of these methods work for me in versions of Python> 3.2 .

0
source share

All Articles