Python内置的open()函数中缓冲区(buffering)有什么作用?

57

Python文档:https://docs.python.org/2/library/functions.html#open

open(name[, mode[, buffering]])  
上述文档说:“可选的缓冲参数指定文件所需的缓冲区大小:0 表示无缓冲,1 表示行缓冲,任何其他正值表示使用大约该大小(以字节为单位)的缓冲区。负缓冲意味着使用系统默认值。如果省略,则使用系统默认值。”。
当我使用时
filedata = open(file.txt,"r",0)  
filedata = open(file.txt,"r",1)  
filedata = open(file.txt,"r",2)
或者
filedata = open(file.txt,"r",-1) 
filedata = open(file.txt,"r")

输出没有变化。上面显示的每一行都以相同的速度打印。

《憨豆先生》是由罗宾·德里科尔撰写并由罗温·艾金森担任主角的英国电视剧系列,共有15集25分钟的剧集。不同的剧集也是由罗宾·德里斯科尔和理查德·柯蒂斯编写的,还有一部分是由本·埃尔顿编写的。其中有13集剧集在1990年1月1日首播的试播集至1995年10月31日的“憨豆先生晚安”期间在ITV播出。一个名为“The Best Bits of Mr. Bean”的片段节目于1995年12月15日播出,而一集名为“Hair by Mr. Bean of London”的剧集直到2006年才在Nickelodeon播出。

那么open()函数中的buffering参数如何有用?最好使用哪个buffering参数值?


1
我可能错了,但我认为缓冲仅在打开文件进行写入时才有可见效果,它会缓冲输入直到达到换行符或文件关闭。这可能会更快一些。 - kirbyfan64sos
当将缓冲区设置为1时,只会显示一行缓冲数据;如果设置为负数,则缓冲区大小将使用系统默认值。 - Curtis
3
您提出这个问题是正确的,我已经为它点赞了。手册和教程都是由自己编写它们的人编写的!他们说:“如果缓冲值设置为0,则不进行缓冲。”那么,先生,什么是缓冲? 我会超过15种编程语言,但我从未听说过这种缓冲方式! - Apostolos
目前,在没有setvbuf()的系统上指定缓冲区大小没有任何效果。指定缓冲区大小的接口不是使用调用setvbuf()的方法完成的,因为在执行任何I/O之后调用该方法可能会导致核心转储,并且没有可靠的方法来确定是否存在这种情况。你知道setvbuf()是什么吗? - pippo1980
5个回答

52
启用缓冲意味着您不直接与操作系统的文件表示或其文件系统API进行交互。相反,一块数据从原始操作系统文件流中读取到缓冲区中,直到被使用完毕,此时会再次从文件中获取数据并储存在缓冲区中。就对象而言,您将获得一个包装底层原始文件流的RawIOBase(表示原始文件流)的BufferedIOBase对象。
那么这样做有什么好处呢?使用原始流可能具有较高的延迟,因为操作系统必须处理物理对象,例如硬盘,这在所有情况下都可能并不可接受。假设您想每5毫秒从文件中读取三个字母,并且您的文件存储在旧硬盘甚至网络文件系统中。与其尝试每5毫秒从原始文件流中读取一次,不如在内存中加载一堆字节到缓冲区中,然后随时使用它。
选择缓冲区大小取决于您如何使用数据。对于上面的示例,缓冲区大小为1个字符会很糟糕,3个字符还可以接受,任何大于3个字符的整数倍且不会引起用户注意的延迟的缓冲区大小都是理想的。

23

您还可以通过从 io 模块调用只读的 DEFAULT_BUFFER_SIZE 属性来检查默认缓冲区大小。

import io
print (io.DEFAULT_BUFFER_SIZE)

此处所述


5
从实用角度来看,缓冲参数决定了何时将发送到流中的数据实际保存到磁盘。如果在没有缓冲参数的情况下打开文件并写入一些内容,你会发现数据只有在退出“with open(...) as foo:”块(或调用文件的“close()”方法)或者达到某个系统确定的默认缓冲区大小时才会被写入。但是,如果设置了“buffering”参数,则会在达到该缓冲区大小时立即写入数据。 因此,在长时间运行的应用程序中向文件发送数据,并希望它在每行之后保存而不仅仅在应用程序退出之后保存,使用例如“open('file.txt', 'w', buffering=1)”就是一个有用的做法。否则,崩溃、停电等可能会导致数据丢失。 参见:How often does python flush to a file?

1

缓冲是将文件的一部分存储在临时内存中,直到文件完全加载的过程。在Python中可以给出不同的值。如果缓冲设置为0,则关闭缓冲。当需要缓冲文件时,缓冲将被设置为1。


-1

将缓冲区设置为-1时,我的文件写入需要13分钟。将缓冲区设置为2 ** 10时,我的文件写入只需要7秒钟。所以,缓冲的目的是加快程序的速度。


2
这是一个缓冲区,意味着它是一个直到被填满并需要排空的储存器。你的程序所需的系统调用更少,因此运行时间更短。 - user8371266
实际上,可悲的是,在生产环境中缓冲并没有起到作用。仍然需要13分钟。我在Psycopg2、OSX和Python3.8文件IO之间遇到了一些奇怪的问题。但在测试中,缓冲确实帮了很大的忙! - John Abraham

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接