题
一节 ://www.greenteapress.com/thinkpython/"rel =“nofollow noreferrer”>这本大概是准确的书,
管道的常见用途是阅读a 压缩文件递增;那 是,没有解压缩整体 事情一下子。以下功能 将压缩文件的名称作为 一个参数并返回一个管道 使用gunzip来解压缩 内容:
def open_gunzip(filename): cmd = 'gunzip -c ' + filename fp = os.popen(cmd) return fp
如果你从fp读取一行 时间,你永远不必存储 内存中或未打开的未压缩文件 磁盘。强>
也许我只是在解释这个错误,但我不知道这是怎么回事。 Python无法通过吐出结果中途暂停gunzip,对吧?我假设在继续输出更多行之前读取输出行之前不会阻塞gunzip,因此一些缓冲区必须捕获所有这些(无论是在Python解释器内还是在OS中,无论是在内存中还是在磁盘上),意思是未压缩文件存储在某处完全...对吗?
解决方案
你的假设是错误的。 gunzip不必查看整个文件来解压缩它。阅读解压缩文件格式。有一个目录,其中包含各个组件的偏移量。
可以将文件解压缩。
“未压缩文件存储在某处...正确?”
不一定。不确定你为什么要假装它或你在哪里阅读它。
所有低级I / O调用都可以阻止。 gunzip中的写入 - 写入管道时 - 可以在管道缓冲区已满时阻塞。这就是定义管道的I / O的方式。管道I / O块。
有关详细信息,请查看管道的手册页。
如果进程尝试从中读取 空管,然后读(2)将
阻止,直到数据可用。如果 进程尝试写入
满管(见下文),然后写(2) 阻止,直到有足够的数据 已从管道中读取以允许 写完成。非阻塞结果 使用fcntl(2)可以实现I / O F_SETFL操作启用
O_NONBLOCK打开文件状态标志。
其他提示
这真的来自 gunzip
实现,而不是来自python。
它是用C语言编写的。它可能使用C的 stdio.h
中的 fwrite()
来编写它的输出。
libc6
实现我使用自动创建一个输出缓冲区,当它被填充时,阻塞 fwrite()
直到它可以写更多。
暂停 gunzip
并不是Python,而是内核在尝试写入时会停止执行 gunzip
(使用 write()
系统调用)到一个完整的缓冲区。这称为阻止IO 。内核维护一个连接管道两端的内部缓冲区,与写入或读取管道的任何进程中发生的任何缓冲无关。
当从具有空缓冲区的管道读取时,Python将同样阻塞,即当前没有写入 gunzip
的任何数据。
管道可视为生产者 - 消费者问题的解决方案。