我有这样的代码:
#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,但我通常不会在同一个文件上多次运行此代码。
答案 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
如果我没有记错的话)这样你就不要读完整个文件后不得不向后滚动。