<h2>解决方案</h2>
<p>为了回答这个问题:<strong>有一个很好的方法来避免这种行为</strong>,尽管这取决于你对友善的含义。基本上,您需要做的是将<code>numpy.savetxt</code>函数包装到另一个函数中,或者在需要的地方使用这里显示的代码块。在</p>
<p>我所做的是把<a href="https://stackoverflow.com/a/28493155/6304064">@mgilson's code</a>和{a2}混合起来回答另一个类似的问题。简而言之,下一步是使用<code>numpy.savetxt</code>保存文件并删除最后一行的代码:</p>
<pre class="lang-py prettyprint-override"><code>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.
</code></pre>
<p><code>os.SEEK_END</code>和{<cd4>}的定义可以找到<a href="https://docs.python.org/3.7/library/os.html#os.SEEK_SET" rel="nofollow noreferrer">here</a>。虽然他们分别只有2和0。在</p>
<h2>代码背后的逻辑</h2>
<p>这里需要注意的是:</p>
<ul>
<li><p>文件以<strong>文本</strong>模式打开,而不是以<strong>二进制模式打开</strong>。这一点很重要,因为如果不指定编码(我们通常不会像对这个问题提供的两个答案那样)来指定编码,那么在文本模式下对文件的写入和读取是依赖于平台的。例如,换行符在Windows或Linux中的读取方式不同。从<a href="https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files" rel="nofollow noreferrer">the documentation</a>:</p>
<blockquote>
<p>Normally, files are opened in text mode, that means, you read and write strings from and to the file, which are encoded in a specific encoding. If encoding is not specified, the default is platform dependent (see <a href="https://docs.python.org/3/library/functions.html#open" rel="nofollow noreferrer">open()</a>). (...)<br/>
<br/>
(...) In text mode, the default when reading is to convert platform-specific line endings (<code>\n</code> on Unix, <code>\r\n</code> on Windows) to just <code>\n</code>. When writing in text mode, the default is to convert occurrences of <code>\n</code> back to platform-specific line endings.</p>
</blockquote></li>
<li><p>在下一行代码<code>fout.seek(0, os.SEEK_END)</code>中,我们将文件的当前位置设置为文件的末尾(请参阅<a href="https://python-reference.readthedocs.io/en/latest/docs/file/seek.html" rel="nofollow noreferrer">seek()</a>的引用)。这是在<em>文本</em>模式下从文件末尾开始的唯一合法操作,我将在本文后面引用。</p></li>
<li>然后,在<code>fout.seek(fout.tell() - NEWLINE_SIZE_IN_BYTES, os.SEEK_SET)</code>行中,我们只告诉Python:
<ul>
<li>将当前位置从当前位置向后设置1个字节:<code>fout.tell() - NEWLINE_SIZE_IN_BYTES</code>。其中<code>tell()</code>只返回当前位置,正如您在<a href="https://python-reference.readthedocs.io/en/latest/docs/file/tell.html" rel="nofollow noreferrer">reference</a>中看到的那样。在</li>
<li>从文件<code>os.SEEK_SET</code>的开头开始。在</li>
</ul></li>
<li>这样做的原因是在<code>seek()</code>方法中,只有<code>tell()</code>返回的偏移才是合法的,正如<a href="https://python-reference.readthedocs.io/en/latest/docs/file/seek.html" rel="nofollow noreferrer">^{<cd10>}</a>文档中所说:
<blockquote>
<p>If the file is opened in text mode (without ‘<code>b</code>’), only offsets returned by <code>tell()</code> are legal. Use of other offsets causes undefined behavior.</p>
</blockquote></li>
<li>最后,<code>truncate()</code>方法只将文件剪切到当前位置。在</li>
</ul>
<h2>另一种方式是二进制模式</h2>
<p>我必须声明<strong>我现在还不太确定在文本模式下执行此操作是否比在二进制模式下更好</strong>尽管其他答案让我这么认为,请看另一个<a href="https://stackoverflow.com/questions/21533391/seeking-from-end-of-file-throwing-unsupported-exception">question</a>。在</p>
<p>在<a href="https://stackoverflow.com/a/28493155/6304064">@mgilson's code</a>之后,我们只需要以二进制模式打开文件。修改后的工作代码为:</p>
^{pr2}$
<p>在Python>;<code>3.2</code>的版本中,这两种方法都适用。在</p>