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

Python:在反向读取文本文件后遍历行,python,loops,lines,Python,Loops,Lines,我正在使用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

我正在使用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
这是一个好办法:

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 10004听我说 10005听到了吗 此代码映射日志文件,使用
rfind()
从文件末尾搜索目标字符串
'*SMTP*'
。然后,它将文件指针定位到目标字符串(使用
seek()
),使用2行不需要的行,最后读取2行感兴趣的行


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

为什么要以反向模式打开文件?因为它是一个大文件,我们只需要从末尾开始的最后一个数据。“我可以这样做”最有可能。不过,您需要付出一点努力。您可以使用以下命令反转python列表:reversed(mylist)查看
file.seek
file.truncate
。这会将整个文件读取到内存中,然后对其进行操作。对于大文件,这将非常缓慢,并且会受到可用内存的限制。使用mmap,操作系统只将所需的页面读取到内存中,而不需要对数据进行操作。性能差距会随着文件大小的增加而扩大。是的,我对一个10米行的文件做了更多的测试,我的解决方案是25/100秒左右,而你的解决方案是1/100秒左右。你的解决方案肯定更好。