Open() 命令缓冲区手动缓冲区操作不起作用



我目前正在使用 Raspberry Pi 创建数据记录功能,我不确定我是否发现了一个小错误。我使用的代码如下:

import sys, time, os
_File = 'TemperatureData1.csv'
_newDir = '/home/pi/Documents/Temperature Data Logs'
_directoryList = os.listdir(_newDir)
os.chdir(_newDir)
# Here I am specifying the file, that I want to write to it, and that
# I want to use a buffer of 5kb
output = open(_File, 'w', 5000)
try:
while (1):
output.write('hin')
time.sleep(0.01)
except KeyboardInterrupt:
print('Keyboard has been pressed')
output.close()
sys.exit(1)

我发现,当我定期查看创建的文件属性时,文件大小会根据默认缓冲区设置 8192 字节而不是我指定的 5kb 增加。但是,当我在 Python 2.7.13 中运行完全相同的程序时,缓冲区大小会根据要求更改为 5kb。

我想知道是否有其他人经历过这种情况,并对让程序在 Python 3.6.3 上运行的解决方案有任何想法?提前谢谢。我可以在python 2.7.13上解决这个问题,这是我纯粹的好奇心导致我发布了这个问题。

Python 在版本 2 中对open的定义是你正在使用的:

open(name[, mode[, buffering]])

在 Python 3 中,open命令略有不同,因为buffering不是位置整数,而是关键字 arg:

open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

这些文档有以下注释:

buffering是用于设置缓冲策略的可选整数。传递0以关闭缓冲(仅在二进制模式下允许),1用于选择行缓冲(仅在文本模式下可用),以及整数>1以指示固定大小的块缓冲区的大小(以字节为单位)。如果未给出缓冲参数,则默认缓冲策略的工作方式如下:

二进制文件以固定大小的块缓冲;缓冲区的大小是使用启发式方法选择的,尝试确定底层设备的"块大小"并回退到 io。DEFAULT_BUFFER_SIZE。在许多系统上,缓冲区的长度通常为 4096 或 8192 字节。 "交互式"文本文件(isatty() 返回 True 的文件)使用行缓冲。其他文本文件对二进制文件使用上述策略。

这个特殊的8192数就是 2^13。

我建议尝试buffering=5000.

我做了更多的研究,并设法找到了一些原因,为什么将"缓冲"设置为大于 1 的值不会手动操作缓冲区到所需的大小(字节)在 python 3 或更高版本中。

这似乎是因为io库在处理文件时使用两个缓冲区,一个文本缓冲区和一个二进制缓冲区。 在文本模式下,文件将根据文本缓冲区刷新(在缓冲> 1 时似乎无法操作)。 相反,缓冲参数操作二进制缓冲区,然后馈送到文本缓冲区中,因此缓冲函数无法按照程序员的预期工作。 以下链接对此进行了进一步说明:

https://bugs.python.org/issue30718

然而,有一个解决方法;你需要在二进制模式下使用open(),而不是文本模式,然后使用io。TextIOWrapper 函数,用于使用二进制缓冲区写入 txt 或 csv 文件。 解决方法如下:

import sys, time, os, io
_File = 'TemperatureData1.csv'
# Open or overwrite the file _file, and use a 20kb buffer in RAM
# before data is saved to disk.
output = open(_File, mode='wb', buffering=700)
output = io.TextIOWrapper(output, write_through=True)
try:
while (1):
output.write('hn')
time.sleep(0.01)
except KeyboardInterrupt:
print('Keyboard has been pressed')
output.close()
sys.exit(1)

最新更新