在Python中读取文件:slurp或filter?

时间:2016-04-23 21:08:37

标签: performance python-3.x

我想比较处理流作为过滤器(即得到一点,处理,冲洗),反对啜饮(即获取所有信息,然后处理)的效果。

然而,当我运行下面的两个代码时,我得到了可比较的结果。我期待在slurp版本中获得更糟糕的结果。

如上所述,代码片段是否会执行任何不同的操作?如果它们是等价的,我怎样才能调整其中一个来测试滤波器/啜食差异?

我正在测试脚本:

jot 100000000 | time python3 dont_slurp.py > /dev/null
jot 100000000 | time python3 slurp.py > /dev/null

Jot生成从1到x的数字。代码片段只是对行进行计算。

过滤器:

import sys
lineno = 0
for line in sys.stdin:
    lineno += 1
    print("{:>6} {}".format(lineno, line[:-1]))

啜食:

import sys

f = sys.stdin
lineno = 0

for line in f:
    lineno += 1
    print('{:>6} {}'.format(lineno, line[:-1]))

1 个答案:

答案 0 :(得分:0)

首先,您的代码示例没有按您的想法进行。所有f = sys.stdin都将f设置为相同的文件句柄。行for line in f:for line in sys.stdin:功能相同。

你想要的是这个:

 import sys

 lineno = 0

 for line in sys.stdin.readlines():
      lineno += 1
      print('{:>6} {}'.format(lineno, line[:-1]))

readlines()返回一个列表,文件中每行一个元素。我相信它是不是一个生成器,所以你得到完整的列表。文件句柄本身充当生成器,一次为您提供一行。

您应该会看到与readline()的性能差异。

然而,答案是"哪个更好?"是"它取决于"。当您逐行读取时,您正在进行系统调用,这反过来会导致操作系统以块的形式从磁盘读取文件内容。这些块可能大于平均线的大小,并且块可能被缓存。这意味着有时你会占用磁盘,花费大量时间,有时你会点击缓存,花费很少时间。

当您一次读取所有内容时,您会立即将文件中的每个字节加载到内存中。如果您有足够的可用内存来容纳所有文件内容,那么这需要与逐行版本完全相同的时间。在这两种情况下,基本上只是按顺序读取整个文件所需的时间,只需要一些开销。

不同之处在于您没有足够的可用内存来容纳整个文件。在这种情况下,您将读取整个文件,但部分内容会被虚拟内存系统交换回磁盘。然后,当您访问该特定行时,他们必须再次被拉入。

确切耗费了多少时间取决于正在使用的内存量,系统上正在进行的其他活动量等等,因此无法对其进行量化。

在出现问题之前,您真的不应该担心这种情况。如果您的程序太慢,那么在代码中执行更自然的操作并且只担心性能。

相关问题