我有一些非常大的文件(超过 1 亿行)。
我需要读他们的最后一行。
由于我是 Linux 用户,因此在 shell/脚本中我使用“tail”。
有没有办法在Python中快速读取文件的最后一行?
也许,使用“seek”,但我不知道这一点。
我得到的最好的就是这个:
from subprocess import run as srun
file = "/my_file"
proc = srun(['/usr/bin/tail', '-1', file], capture_output=True)
last_line = proc.stdout
我尝试的所有其他 pythonic 代码都比调用外部 /usr/bin/tail
慢我还阅读了这些不能满足我需求的帖子:
如何实现 tail -F 的 Python 等价物?
头尾在一条线上
因为我想要一定的执行速度并避免内存过载。
编辑: 我尝试根据评论了解我的理解,然后……
我的行为很奇怪:
>>> with open("./Python/nombres_premiers", "r") as f:
... a = f.seek(0,2)
... l = ""
... for i in range(a-2,0,-1):
... f.seek(i)
... l = f.readline() + l
... if l[0]=="\n":
... break
...
1023648626
1023648625
1023648624
1023648623
1023648622
1023648621
1023648620
1023648619
1023648618
1023648617
1023648616
>>> l
'\n2001098251\n001098251\n01098251\n1098251\n098251\n98251\n8251\n251\n51\n1\n'
>>> with open("./Python/nombres_premiers", "r") as f:
... a = f.seek(0,2)
... l = ""
... for i in range(a-2,0,-1):
... f.seek(i)
... l = f.readline()
... if l[0]=="\n":
... break
...
1023648626
1023648625
1023648624
1023648623
1023648622
1023648621
1023648620
1023648619
1023648618
1023648617
1023648616
>>> l
'\n'
如何获得
l = 2001098251
?
tail 不支持任意长的行——它获取文件的最后一个块并从那里迭代。自己做同样的事情可能看起来像:
def last_line(f, bufsize=4096):
end_off = f.seek(0, 2)
f.seek(max(end_off - bufsize, 0), 0)
lastline = None
while (line := f.readline()):
if line[-1] == '\n':
lastline = line
else:
break # last line is not yet completely written; ignore it
return lastline[:-1] if lastline is not None else None
import sys
print(last_line(open(sys.argv[1], 'r')))
请注意,如果您想在文件随着时间的推移而编辑时继续阅读新内容,则应该使用 inotify 来监视更改。 https://stackoverflow.com/a/78969468/14122演示了这一点。
使用 seek()、read() 和 readline(),
我可以快速检索文本文件的最后一行:
with open("My_File", "r") as f:
n = f.seek(0,2)
for i in range(n-2, 0, -1):
f.seek(i)
if f.read(1)=="\n":
s = f.readline().replace("\n", "")
break
编辑:如果文件只有 1 行,则将
range(n-2, 1, -1)
更改为 range(n-2, 0, -1)
。s = f.readline()[:-1]
替换为 s = f.readline().replace("\n", "")
。