【问题标题】:Difference between iterating over a file-like and calling readline遍历类文件和调用 readline 之间的区别
【发布时间】:2012-04-18 05:21:15
【问题描述】:

我一直认为在 Python 中迭代类文件相当于在循环中调用它的 readline 方法,但今天我发现了一种情况并非如此。具体来说,我有一个Popen'd 进程p where

list(itertools.takewhile(lambda x: x != "\n",
                         p.stdout))

挂起(可能是因为 p 等待输入;stdinstdout 都是我的 Python 进程的管道),而以下工作:

list(itertools.takewhile(lambda x: x != "\n",
                         iter(p.stdout.readline, "")))

有人能解释一下区别吗?

【问题讨论】:

  • 旁注:你可以用iter(f.readline, None)代替fiter(),甚至用iter(f.readline, "\n")代替takewhile()
  • 您看到的问题与缓冲有关:file.__iter__() 在某种程度上比file.readline() 更积极地缓冲——这也是您不能混合它们的原因。目前懒得研究细节并把它变成答案……
  • @SvenMarnach:你的意思是iter(f.readline, ""),但是是的,谢谢,我一直忘记这个:)
  • 我用None模拟while True
  • 很高兴看到你毕竟是人类,而且什么都不知道:-)

标签: python io iterator subprocess pipe


【解决方案1】:

区别纯粹在于迭代的实现与readline 方法。文件迭代读取块(默认为 8 KB),然后在使用缓冲区时将缓冲区拆分为行。另一方面,readline 方法注意不要读取超过一行,这意味着逐个字符地读取。在块中读取效率更高,但这意味着您不能在读取之间混合文件上的其他操作。期望是,当您遍历文件时,您的意图是顺序读取所有行,并且您不会对其进行其他操作。 readline 方法不能做出这样的假设。

正如 Sven Marnach 在他对您的问题的评论中所暗示的那样,您可以使用 iter(f.readline, '') 获取一个迭代器,该迭代器从文件中读取行而不以块的形式读取,但会以性能为代价。 p>

【讨论】:

  • 你知道在 CPython 源代码中哪里可以找到文件迭代器的实现吗?
  • Objects/fileobject.c。文件对象是它们自己的迭代器,所以没有单独的类型。 file.readlinefile_readline,通过file_iternext 完成迭代。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-02
  • 1970-01-01
  • 1970-01-01
  • 2011-03-30
  • 1970-01-01
  • 2014-07-23
  • 2013-11-07
相关资源
最近更新 更多