Python:itertools.islice不在循环中工作

时间:2011-02-16 18:19:20

标签: python file-io itertools

我有这样的代码:

#opened file f
goto_line = num_lines #Total number of lines
while not found:
   line_str = next(itertools.islice(f, goto_line - 1, goto_line))
   goto_line = goto_line/2
   #checks for data, sets found to True if needed

line_str在第一次传递时是正确的,但是之后的每次传递都是读取不同的线然后它应该。

例如,goto_line从1000开始。它读取1000行就好了。然后是下一个循环,goto_line是500,但它不读取500行。它读取的行更接近1000。

我正在尝试读取大文件中的特定行,而不必阅读超过必要的内容。有时它会向后跳到一条线,有时会向前跳。

我确实尝试过linecache,但我通常不会在同一个文件上多次运行此代码。

2 个答案:

答案 0 :(得分:5)

Python迭代器只能使用一次。这是最简单的例子。以下代码

from itertools import islice
a = range(10)
i = iter(a)
print list(islice(i, 1, 3))
print list(islice(i, 1, 3))
print list(islice(i, 1, 3))
print list(islice(i, 1, 3))

打印

[1, 2]
[4, 5]
[7, 8]
[]

切片总是从我们上次停止的地方开始。

使代码工作的最简单方法是使用f.readlines()获取文件中的行列表,然后使用普通的Python列表切片[i:j]。如果你真的想使用islice(),你可以每次使用f.seek(0)从头开始阅读文件,但效率非常低。

答案 1 :(得分:0)

你不能(这种方式 - 也许有一些方法取决于文件的打开方式)回到文件中。标准文件迭代器(事实上,大多数迭代器 - Python的迭代器协议仅支持前向迭代器)仅向前移动 。因此,在阅读k行之后,读取另一条k/2行实际上会给出k+k/2行。

可以尝试将整个文件读入内存,但是你有很多数据,所以内存消耗可能成为一个问题。您可以使用file.seek滚动文件。但这仍然是很多工作 - 也许你可以使用memory-mapped file?只有当行是固定大小时才有可能。如果有必要,你可以在一次迭代中预先计算你想要检查的行号并保存所有这些行(不应该太多,大约int(log_2(line_count)) + 1如果我没有记错的话)这样你就不要读完整个文件后不得不向后滚动。