Python:反向读取文本文件后遍历行

Python: iterate through lines after reverse reading a text file

我正在使用 Python 3.4。

我有一个这样的日志文件:

10001 ...
10002 * SMTP *
10003 skip me
10004 read me
10005 read me

脚本的目标是以反向模式打开文件,遍历行直到我在其中找到'* SMTP *'(在示例中是第 10002 行),然后我必须返回并跳过一行并阅读接下来的两行(在示例行 10004 和 10005 中)。

我该怎么做?

with open (file) as textfile:
    lines = textfile.read().split("\n")
    lines.reverse()
    if lines.index("* SMTP *"):
        Ind =  int(lines.index("* SMTP *"))
        print lines[Ind-2]
        print lines[Ind-3]
        break

这只会在您的日志文件中找到最近出现的 * SMTP *,它是脏的,但可以完成工作。

做了一些测试来比较@mhawke mmap 和我的。测试是在 150k 行测试文件上完成的。

mmap

real 0m0.024s
user 0m0.016s
sys  0m0.008s

我的解决方案

real 0m0.038s
user 0m0.026s
sys  0m0.012s

mmap 是个不错的选择:

import mmap

SEARCH_TEXT = b'* SMTP *'
SKIP_LINES = 2
KEEP_LINES = 2

with open('log.txt', 'rb') as f:
    log = mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ)
    n = log.rfind(SEARCH_TEXT)
    if n == -1:
        print('{!r} not found'.format(SEARCH_TEXT))
    else:
        log.seek(n)
        for i in range(SKIP_LINES):
            _ = log.readline()

        print(''.join(log.readline().decode() for _ in range(KEEP_LINES)))

输出

10004 read me
10005 read me

此代码映射日志文件,从文件末尾 rfind() 搜索目标字符串 '* SMTP *'。然后它将文件指针定位到目标字符串(使用 seek()),消耗 2 条不需要的行,最后读取 2 条感兴趣的行。

mmap 是高效的,因为 OS 为您的应用程序处理数据从磁盘到内存的分页。它不会读取整个文件,因此对于大文件来说是一个很好的策略。