【问题标题】:Is there a way to read file in reverse using with open using Python有没有办法使用 Python 反向读取文件
【发布时间】:2019-04-26 13:53:18
【问题描述】:

我正在尝试读取 file.out 服务器文件,但我只需要读取日期时间范围内的最新数据。

是否可以使用带有模式(方法)的with open() 反向读取文件?

a+ 模式可以访问文件末尾:

    ``a+''  Open for reading and writing.  The file is created if it does not
      exist. The stream is positioned at the end of the file. Subsequent writes
      to the file will always end up at the then current end of the file, 
      irrespective of any intervening fseek(3) or similar.

有没有办法使用 a+ 或其他模式(方法)来访问文件末尾并读取特定范围?

由于常规r 模式从头开始读取文件

    with open('file.out','r') as file:

已尝试使用reversed()

    for line in reversed(list(open('file.out').readlines())):

但它没有为我返回任何行。

或者还有其他方法可以反向读取文件...帮助

编辑

到目前为止我得到了什么:

import os
import time
from datetime import datetime as dt

start_0 = dt.strptime('2019-01-27','%Y-%m-%d')
stop_0 = dt.strptime('2019-01-27','%Y-%m-%d')
start_1 = dt.strptime('09:34:11.057','%H:%M:%S.%f')
stop_1 = dt.strptime('09:59:43.534','%H:%M:%S.%f')

os.system("touch temp_file.txt")
process_start = time.clock()
count = 0
print("reading data...")
for line in reversed(list(open('file.out'))):
    try:
        th = dt.strptime(line.split()[0],'%Y-%m-%d')
        tm = dt.strptime(line.split()[1],'%H:%M:%S.%f')

        if (th == start_0) and (th <= stop_0):
            if (tm > start_1) and (tm < stop_1):
                count += 1
                print("%d occurancies" % (count))
                os.system("echo '"+line.rstrip()+"' >> temp_file.txt")
        if (th == start_0) and (tm < start_1):
            break
    except KeyboardInterrupt:
        print("\nLast line before interrupt:%s" % (str(line)))
        break
    except IndexError as err:
        continue
    except ValueError as err:
        continue
process_finish = time.clock()
print("Done:" + str(process_finish - process_start) + " seconds.")

我添加了这些限制,因此当我找到行时,它至少可以打印出出现的事件,然后停止读取文件。

问题是它正在读取,但是速度太慢了..

编辑 2

(2019-04-29 9.34am)

我收到的所有答案都适用于反向阅读日志,但在我(也许对于其他人)的情况下,当你有 n GB 大小的日志时,下面 Rocky 的答案最适合我。

适合我的代码:

(我只在 Rocky 的代码中添加了 for 循环):

import collections

log_lines = collections.deque()
for line in open("file.out", "r"):
    log_lines.appendleft(line)
    if len(log_lines) > number_of_rows:
        log_lines.pop()

log_lines = list(log_lines)
for line in log_lines:
    print(str(line).split("\n"))

谢谢大家,所有答案都有效。

-lpkej

【问题讨论】:

标签: python file parsing logging


【解决方案1】:

open 参数无法做到这一点,但如果您想读取大文件的最后一部分而不将该文件加载到内存中,(reversed(list(fp)) 将这样做)您可以使用 2 pass解决方案。

LINES_FROM_END = 1000
with open(FILEPATH, "r") as fin:
    s = 0
    while fin.readline(): # fixed typo, readlines() will read everything...
        s += 1
    fin.seek(0)
    mylines = []
    for i, e in enumerate(fin):
        if i >= s - LINES_FROM_END:
            mylines.append(e)

这不会将您的文件保留在内存中,您也可以使用 collections.deque 将其减少到一次处理

# one pass (a lot faster):
mylines = collections.deque()
for line in open(FILEPATH, "r"):
    mylines.appendleft(line)
    if len(mylines) > LINES_FROM_END:
        mylines.pop()

mylines = list(mylines)
# mylines will contain #LINES_FROM_END count of lines from the end.

【讨论】:

  • collections.deque() 为我工作,打印线条流畅。谢谢洛基你摇滚!
【解决方案2】:

当然有:

filename = 'data.txt'
for line in reversed(list(open(filename))):
    print(line.rstrip())

编辑: 如 cmets 中所述,这会将整个文件读入内存。此解决方案不应用于大文件。

【讨论】:

  • 将整个文件读入内存,然后反向迭代行(与 OP 已经尝试过的没有本质区别)。
  • 我刚刚解决了这个问题,以回应“但它没有为我返回任何行。”。虽然效率不高,但如果他不处理大文件,它可能就是 OP 所追求的。
  • @mlotz 这是一种反向读取的方法,但它不适合我的情况。感谢您的回答。
【解决方案3】:

另一种选择是mmap.mmap 文件,然后从末尾使用rfind 搜索newlines,然后切出行。

【讨论】:

    【解决方案4】:

    嘿,m8,我已经让这段代码对我有用,我可以以相反的顺序在我的文件中读取。希望能帮助到你 :) 我从创建一个新的文本文件开始,所以我不知道这对你有多重要。

    def main():
    f = open("Textfile.txt", "w+")
    for i in range(10):
        f.write("line number %d\r\n" % (i+1))
    
    f.close
    def readReversed():
    for line in reversed(list(open("Textfile.txt"))):
        print(line.rstrip())
    
    main()
    readReversed()
    

    【讨论】:

    • 这个反向读取代码也可以,我试过了。但对我来说并不是很好,因为我有大量的日志要解析。对于其他文件读取目的,我确信这段代码很合适。感谢您的回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-10
    相关资源
    最近更新 更多