Python管道 - 增量读取输出时会发生什么

时间:2009-10-23 09:33:58

标签: python unix pipe

根据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中,无论是在内存中还是在磁盘上),意思是未压缩文件存储在某处完全...对吗?

3 个答案:

答案 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的解决方案。