三种不同的解决方案:
1) 又快又脏,见约翰的回答:
with open(file_name) as fid:
lines = fid.readlines()
for line in lines[:-n_skip]:
do_something_with(line)
这种方法的缺点是你必须先读取内存中的所有行,这对于大文件来说可能是个问题。
2) 两遍
处理文件两次,一次计算行数n_lines,第二次只处理第一行n_lines - n_skip:
# first pass to count
with open(file_name) as fid:
n_lines = sum(1 for line in fid)
# second pass to actually do something
with open(file_name) as fid:
for i_line in xrange(n_lines - n_skip): # does nothing if n_lines <= n_skip
line = fid.readline()
do_something_with(line)
这种方法的缺点是您必须对文件进行两次迭代,这在某些情况下可能会比较慢。不过,好在你的内存中永远不会超过一行。
3) 使用缓冲区,类似于 Serge 的解决方案
如果您只想对文件进行一次迭代,您只有在知道i + n_skip 行存在时才能确定可以处理行i。这意味着您必须首先将n_skip 行保存在临时缓冲区中。一种方法是实现某种 FIFO 缓冲区(例如,使用实现循环缓冲区的生成器函数):
def fifo(it, n):
buffer = [None] * n # preallocate buffer
i = 0
full = False
for item in it: # leaves last n items in buffer when iterator is exhausted
if full:
yield buffer[i] # yield old item before storing new item
buffer[i] = item
i = (i + 1) % n
if i == 0: # wrapped around at least once
full = True
使用一系列数字进行快速测试:
In [12]: for i in fifo(range(20), 5):
...: print i,
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
您对文件的使用方式:
with open(file_name) as fid:
for line in fifo(fid, n_skip):
do_something_with(line)
请注意,这需要足够的内存来临时存储n_skip 行,但这仍然比在第一个解决方案中读取内存中的所有行要好。
这 3 种方法中哪一种最好是代码复杂性、内存和速度之间的权衡,这取决于您的具体应用程序。