numpy.savetxt()似乎总是在文件末尾添加一个新行。有没有一种避免这种行为的好方法?将新行字符替换为其他字符并没有帮助。
我不认为这对我的代码来说是特别的,但写作正在这样做(模型是一个3D数组):
np.savetxt(modelFile, model, delimiter=",", fmt='%.3f')
答案 0 :(得分:5)
我不确定为什么这很重要,或者是否有办法在numpy端防止它(我在文档中没有看到任何内容......)但你可以写完之后可能会在文件中找回然后截断。 e.g。
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()
注意:要向后搜索,字节大小必须为负
答案 1 :(得分:0)
要回答这个问题:有一种避免这种行为的好方法,尽管这取决于您对“好”的含义。基本上,您需要做的就是将numpy.savetxt
函数包装到另一个函数中,或者只在需要的地方使用此处显示的代码块。
我所做的是将@mgilson's code和code provided混合使用,以回答另一个类似的问题。简而言之,下一个代码是使用numpy.savetxt
保存文件并消除最后一行:
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.
here可以找到os.SEEK_END
和os.SEEK_SET
的定义。尽管它们分别是2和0。
这里要注意一些事情:
该文件以文本模式而不是二进制模式打开。这很重要,因为如果您不指定编码(在此问题提供的两个答案中我们通常不这样做),则以文本模式在文件中进行读写取决于平台而定。例如,换行符在Windows或Linux中的读取方式有所不同。来自the documentation:
通常,文件以文本模式打开,也就是说,您从文件中读取和写入字符串,这些字符串以特定的编码进行编码。如果未指定编码,则默认值为平台相关(请参见open())。 (...)
(...)在文本模式下,读取时的默认设置是将特定于平台的行尾(在Unix上为\n
,在Windows上为\r\n
)转换为\n
。在文本模式下书写时,默认设置是将\n
的出现转换回特定于平台的行结尾。
在代码的下一行fout.seek(0, os.SEEK_END)
中,我们将文件的当前位置设置为文件的末尾(请参阅seek()的参考资料)。这是 text 模式下从文件末尾开始的唯一合法操作,我将在本文后面引用。
fout.seek(fout.tell() - NEWLINE_SIZE_IN_BYTES, os.SEEK_SET)
行中,我们告诉Python:
fout.tell() - NEWLINE_SIZE_IN_BYTES
。 tell()
仅返回当前位置,如您在reference中看到的那样。os.SEEK_SET
的开头开始。seek()
方法中,仅tell()
返回的偏移量是合法的,正如seek()
文档中所说:
如果文件以文本模式打开(不带“
b
”),则仅tell()
返回的偏移量是合法的。使用其他偏移量会导致不确定的行为。
truncate()
方法现在只能将文件剪切到当前位置。我必须声明我现在不太确定在文本模式下执行此操作是否比在二进制模式下好,尽管其他答案让我这么认为,请参阅其他question
在@mgilson's 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()
以上两种方式均适用于Python> 3.2
版本。