我想逐行读取文件,除了最后N行。我如何知道在Python中如何停止,而无需到达文件末尾并回溯/放弃最后N行?是要求#lines = X,并且循环(X-N)是一个很好的方法来解决这个问题?简单的方法是不读取Python中文件的最后N行
什么是最简单/最Pythonic这样做?
我想逐行读取文件,除了最后N行。我如何知道在Python中如何停止,而无需到达文件末尾并回溯/放弃最后N行?是要求#lines = X,并且循环(X-N)是一个很好的方法来解决这个问题?简单的方法是不读取Python中文件的最后N行
什么是最简单/最Pythonic这样做?
三种不同的解决方案:
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)使用
如果你想遍历文件只是一次缓冲,类似塞尔的解决方案,你只知道为确保您可以处理线i
,如果你知道行i + n_skip
存在。这意味着您必须首先将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
线,但是这仍然比读备忘录中的所有行更好像第一个解决方案一样。
这三种方法中哪一种最好是在代码复杂度,内存和速度之间取舍,这取决于您的确切应用。
要读取最后X行的所有行,您需要知道最后一行X行的起始位置。你将需要这个信息。 有几种方法可以获取这些信息。
鉴于我们所知道的文件必须读到尾,以确定有多少行有,这是我在阅读了最后n
线“简单/最Python的方式”的尝试:
with open(foo, 'r') as f:
lines = f.readlines()[:-n]
除非你有办法事先知道实际的行数,否则你将不得不阅读整个文件。
但是当我想你想过程由行的文件行除了N个最后一行,你可以不用加载在内存中的所有文件,并只保留一个为N行名单:
with open(file) as fd:
lines = []
try:
for i in range(N):
lines.append(next(fd))
i = 0
for line in fd:
# process lines[i]
print (lines[i].rstrip())
lines[i] = line
i = (i + 1) % N
except StopIteration:
print "less than %d lines" % (N,)
一般来说,如果行可以是可变长度的,那么*没有办法* Pythonic或其他方法知道文件中有多少行没有读取。 – 2014-11-02 05:37:53
你可以使用'readlines'读取文件,然后应用'len'来获得文件中的总行数,现在你可以做 – Hackaholic 2014-11-02 05:39:03
@Hackaholic你刚刚读过这些行......不是len,你可以切片[:-N] ...这是“丢弃最后N行”... – 2014-11-02 05:42:42