Python全栈工程师

20.4-缓冲区

2019-09-25  本文已影响0人  BeautifulSoulpy

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

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)

一般来说,只需要记住:

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

猜你喜欢

热点阅读