16

我正在编写一个程序,该程序将定期解析 Apache 日志文件以记录其访问者、带宽使用情况等。

问题是,我不想打开日志并解析我已经解析过的数据。例如:

line1
line2
line3

如果我解析该文件,我将保存所有行,然后保存该偏移量。这样,当我再次解析它时,我得到:

line1
line2
line3 - The log will open from this point
line4
line5

第二轮,我会得到line4和line5。希望这是有道理的......

我需要知道的是,我该如何做到这一点?Python具有用于指定偏移量的seek()函数......那么我是否只是在解析后获取日志的文件大小(以字节为单位),然后在第二次记录它时将其用作偏移量(在seek()中)?

我似乎想不出一种方法来编写这个>.<

4

8 回答 8

15

seek由于类的和tell方法,您可以管理文件中的位置,file请参见 https://docs.python.org/2/tutorial/inputoutput.html

tell方法会告诉你下次打开时在哪里寻找

于 2010-07-21T12:38:33.207 回答
4
log = open('myfile.log')
pos = open('pos.dat','w')
print log.readline()
pos.write(str(f.tell())
log.close()
pos.close()

log = open('myfile.log')
pos = open('pos.dat')
log.seek(int(pos.readline()))
print log.readline()

当然,您不应该那样使用它——您应该将操作包装在save_position(myfile)和之类load_position(myfile)的函数中,但功能就在那里。

于 2010-07-21T12:44:54.533 回答
1

如果您的日志文件很容易放入内存中(也就是说,您有一个合理的轮换策略),您可以轻松地执行以下操作:

log_lines = open('logfile','r').readlines()
last_line = get_last_lineprocessed() #From some persistent storage
last_line = parse_log(log_lines[last_line:])
store_last_lineprocessed(last_line)

如果你不能这样做,你可以使用类似的东西(参见接受的答案的使用 seek and tell,以防你需要用它们来做)用 Python 获取文件的最后 n 行,类似于 tail

于 2010-07-21T12:38:31.293 回答
0

如果您每行解析日志行,则可以从上次解析中保存行号。然后,您下次必须从好行开始阅读它。

当您必须位于文件中非常特定的位置时,查找更有用。

于 2010-07-21T12:40:28.020 回答
0

简单但不推荐:):

last_line_processed = get_last_line_processed()    
with open('file.log') as log
    for record_number, record in enumerate(log):
        if record_number >= last_line_processed:
            parse_log(record)
于 2010-07-21T12:41:47.363 回答
0

请注意,您可以从文件末尾开始在 python 中查找():

f.seek(-3, os.SEEK_END)

将读取位置距 EOF 3 行。

但是,为什么不使用 diff,无论是从 shell 还是使用difflib

于 2010-07-21T12:45:23.833 回答
0

这是使用您的长度建议和告诉方法证明的代码:

beginning="""line1
line2
line3"""

end="""- The log will open from this point
line4
line5"""

openfile= open('log.txt','w')
openfile.write(beginning)
endstarts=openfile.tell()
openfile.close()

open('log.txt','a').write(end)
print open('log.txt').read()

print("\nAgain:")
end2 = open('log.txt','r')
end2.seek(len(beginning))

print end2.read()  ## wrong by two too little because of magic newlines in Windows
end2.seek(endstarts)

print "\nOk in Windows also"
print end2.read()
end2.close()
于 2010-07-21T12:59:16.210 回答
0

这是一个有效且安全的片段,可以将读取的偏移量保存在并行文件中。基本上是python中的logtail。

with open(filename) as log_fd:
    offset_filename = os.path.join(OFFSET_ROOT_DIR,filename)
    if not os.path.exists(offset_filename):
        os.makedirs(os.path.dirname(offset_filename))
        with open(offset_filename, 'w') as offset_fd:
            offset_fd.write(str(0))
    with open(offset_filename, 'r+') as offset_fd:
        log_fd.seek(int(offset_fd.readline()) or 0)
        new_logrows_handler(log_fd.readlines())
        offset_fd.seek(0)
        offset_fd.write(str(log_fd.tell()))
于 2012-02-24T10:53:04.347 回答