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