怎么设置 python 中 open 的 buffering 参数

2016-12-18 13:24:14 +08:00
 wisefree

buffering>1

f = open('./test.txt', 'w', buffering=1024)

f.write('+'*4)

打开 test.txt 发现已经有了++++,缓冲区不是设置成了 1024 么,怎么会这样

buffering=1

f = open('./test.txt', 'w', buffering=1)

f.write('+'*4)

打开 test.txt 没有++++,这种情况是符合帮助文章的描述的

请问这是怎么回事呢?>_<

5266 次点击
所在节点    Python
16 条回复
a87150
2016-12-18 14:48:22 +08:00
以我粗浅的了解, 0 是关, 1 是开。
wisefree
2016-12-18 14:58:53 +08:00
@a87150 不是这样的。我按照 python 帮助文档定义进行操作,没有得到预期的结果
Kisesy
2016-12-18 15:08:44 +08:00
f = open('./test.txt', 'w', buffering=1024)
f.write('+'*4)
import time
time.sleep(10)

这样呢,在十秒内看看里面有没有
Kisesy
2016-12-18 15:10:11 +08:00
额,看错问题了
wwqgtxx
2016-12-18 16:13:08 +08:00
如果你程序只有这几行,会在程序结束的时候自动 flush ,你如果要测试,在 write 后 sleep 很长时间,同时在程序未结束的时候查看文件
wisefree
2016-12-18 18:53:53 +08:00
@Kisesy 10 秒内看看里面没有,就算 10s 后里面也没有, f.flush()后才有,:),谢谢!
wisefree
2016-12-18 18:55:55 +08:00
@wwqgtxx 嗯嗯,确实如此,谢谢啦。 sleep(10), 10 秒内里面没有内容, 10s 后里面也没有, f.flush()才有++++
为什么要自动 flush 呢?这个真心让人困惑
mringg
2016-12-18 21:39:04 +08:00
你用控制台尝试下,程序退出会被强制 flush 的
wwqgtxx
2016-12-19 01:00:50 +08:00
@wisefree 如果在程序结束还不强制 flush ,那这个 buffering 本身设计就不合理了
而且 open 的 buffering 是由系统实现的,系统在关闭所有输入输出流之前都会强制 flush
至于问为什么,我只能说符合大部分人的理解观念
要是不自动 flush 会带来无尽的坑
SlipStupig
2016-12-19 02:21:22 +08:00
给一个官方的解释:“ The optional buffering argument specifies the file ’ s desired buffer size: 0 means unbuffered, 1 means line buffered, any other positive value means use a buffer of (approximately) that size (in bytes). A negative buffering means to use the system default, which is usually line buffered for tty devices and fully buffered for other files. If omitted, the system default is used. ”
1 代表启用, 0 代表关闭,为负的时候,由系统来管理,一般缓存 tty 设备上
wisefree
2016-12-19 08:18:52 +08:00
@SlipStupig 谢啦,但是帮助文档的解释不能回答我的问题
wisefree
2016-12-19 08:25:26 +08:00
@mringg 确实如此,谢啦!

运行环境: virtualbox ubuntu ipython3.5.1
我在 ipython 控制台中,打开了两个终端,我尝试了一下如下代码

终端 1 : ipython (还未退出)
``` python
f = open('test.txt', 'w', buffering=4)

f.write('+'*4)

f.write('+')
```
终端 2
tail -f test.txt

但是 test.txt 没有出现+


在终端 1 中输入 exit ,退出 ipython
终端 2 出现了 5 个+


通过你们的解释,这个我能理解了,程序中强制 flush

但是程序没有退出,为什么没有进行 flush 呢?
wisefree
2016-12-19 08:26:46 +08:00
@wwqgtxx 谢谢!现在我在终端运行代码,终端退出和未退出的情形让我有点困惑。

运行环境: virtualbox ubuntu ipython3.5.1
我在 ipython 控制台中,打开了两个终端,我尝试了一下如下代码

终端 1 : ipython (还未退出)
``` python
f = open('test.txt', 'w', buffering=4)

f.write('+'*4)

f.write('+')
```
终端 2
tail -f test.txt

但是 test.txt 没有出现+


在终端 1 中输入 exit ,退出 ipython
终端 2 出现了 5 个+


通过你们的解释,这个我能理解了,程序退出强制 flush

但是程序没有退出,为什么没有进行 flush 呢?
wwqgtxx
2016-12-19 08:51:11 +08:00
@wisefree 很多系统在实现的时候缓冲区并不是只有一个,你这个最上层的缓冲区缓冲区满了填充了下层缓冲区而已。
比如一般你 read()的缓冲区是 glibc 实现的,而系统的内核区还是有驱动级别的缓冲区,硬件本身也是有缓冲区的。而且并不能保证 python 给你返回的就是原生系统实现的 file 对象,可能是 cpython 包装了一层
而 flush 会强制要求系统底层刷新(虽然系统到底是否执行是另一回事)
wwqgtxx
2016-12-19 08:53:09 +08:00
这也就是为什么文件的读写经常需要加锁,因为在多进程同时读写同一个文件的时间很容易出现这种缓存不一致的情况
wisefree
2016-12-19 10:05:53 +08:00
@wwqgtxx 谢谢!答案太精彩了!越往下学,好像内容越来越多了,~_~

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/328429

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX