我们一路奋斗,不是为了改变世界,而是为了,不让世界改变我们!

I/O 操作很耗时,为了提高效率,我们就要减少 I/O 操作的次数,我们使用的手段就是为文件设置一个缓冲区。
先进先出;缓冲区取自 操作系统原理;
文件系统、网络系统属于操作系统,Python使用的还是操作系统的能力;不学习操作系统还是不会编程;
缓冲分类
文件的缓冲一般分为“全缓冲”、“行缓冲”、“无缓冲”。
“全缓冲”就是我在上面说的,缓冲区有一定大小,数据凑齐了这个大小就进行一次系统调用;
“行缓冲”是在某些终端设备中上使用,碰到换行符进行一次系统调用;
“无缓冲”是在一些不希望进行缓冲的设备上,比如串口设备,我们就需要及时把数据发送到串口上去。
buffering 是一个可选的整数,用于设置缓冲策略。
传递0以切换缓冲关闭(仅允许在二进制模式下)。
传递1选择 行缓冲(仅在文本模式下可用)。
传递大于1的整数以指示固定大小的块缓冲区的大小(以字节为单位)。
如果没有给出 buffering 参数,则默认缓冲策略的工作方式如下:
二进制文件以固定大小的块进行缓冲;使用启发式方法选择缓冲区的大小,尝试确定底层设备的“块大小”或使用 io.DEFAULT_BUFFER_SIZE。在许多系统上,缓冲区的长度通常为4096或8192字节。
Python 中默认的文件对象缓冲行为
缓冲区为一个内存空间,一般来说是一个FIFO队列,到缓冲区满了或者达到阙值,数据才会flush到磁盘;
先看二进制模式:
import io
f = open('test4','w+b')
print(io.DEFAULT_BUFFER_SIZE) | 8192
f.write(b'magedu') | 6
f.write(b'xyz') | 3
f.seek(0) | 0
f.read() | b'mageduxyz'
f.seek(0) | 0
f.write(b'xyz') | 3
f.read() | b'eduxyz' # 完全覆盖;
只要seek()一次,就会将缓冲强行写入一次;
flush()将缓冲区数据写入磁盘close()关闭前会调用flush()
io.DEFAULT_BUFFER_SIZE缺省缓冲区大小、字节;
f = open('test5','wb+')
print(io.DEFAULT_BUFFER_SIZE)
f.write("magedu.com".encode())
f.seek(0)
f.read() | b'magedu.com'
f.write("www.magedu.com".encode())
f.flush()
f.read() | magedu.comwww.magedu.com
文件系统的批处理
缓冲区大小是有用的;
f = open('test5','w+b',4)
print(io.DEFAULT_BUFFER_SIZE)
f.write(b'mag')
f.write(b'x')
f.write(b'x')
f.read()
---------------
magx
f = open('test5','rb+',1) # 缓冲区大小为1,不是文本模式;
行缓冲模式 bufferring = 1(了解就行,很少用)
f = open('test6','r+',1)
print(io.DEFAULT_BUFFER_SIZE) # 8192
f.write('mag'*10)
f.write('\n')
f.seek(0)
f.read()
-------------------
'magmagmagmagmagmagmagmagmagmag\n'
文本模式下,10并不代表缓冲区大小,实际 bufferring = 缺省值8192(了解就行,很少用)
f = open('test6','r+',10)

一般来说,只需要记住:
- 文本模式,一般都用默认缓冲区大小
- 二进制模式,是一个个字节的操作,可以指定buffer的大小
- 一般来说,默认缓冲区大小是个比较好的选择,除非明确知道,否则不调整它
- 一般编程中,明确知道需要写磁盘了,都会手动调用一次flush,而不是等到自动flush或者close的时候
网友评论