免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 22737 | 回复: 9
打印 上一主题 下一主题

请问:如何用python获取文件的最后一行,文件可能会比较大 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-09-05 11:31 |只看该作者 |倒序浏览
本帖最后由 lzzfriend 于 2013-09-05 11:50 编辑

我主要是分析日志获取当前的进度等信息,
想取文件最后一行进行分析

贴上我的程序
def get_lastline(logfile):
    fd = open(logfile,'r')
    linecount = len(fd.readlines())
    print linecount
    targetLine = ''
    lineNo = 0
    while 1:
        mLine = fd.readline()
        if not mLine:
            print "find empty line:%s,mLine:%s" % (lineNo,mLine)
            if(lineNo >= linecount):
                break;
        lineNo += 1;
        if (linecount == lineNo):
            targetLine = mLine
            break
    fd.close()
    return targetLine
   
if __name__ == '__main__':
    filename='/home/lzh/movies/sample_h264_100kbit.mp4.log'
    lastline=get_lastline(filename)
    print lastline
   
但每次都在第0行跳出,我查看了一下,我的文件第一行是:
2013-08-12 18:05:48     PID=29946


那位大拿帮忙看一下,谢谢

论坛徽章:
0
2 [报告]
发表于 2013-09-05 13:42 |只看该作者
Linux平台有一个tail命令,tail -f filename.log 就会打印文件最后新增加的内容

可以参考这个思路

论坛徽章:
11
技术图书徽章
日期:2014-03-01 14:44:34天蝎座
日期:2014-05-21 22:11:59金牛座
日期:2014-05-30 17:06:14
3 [报告]
发表于 2013-09-05 13:50 |只看该作者
回复 1# lzzfriend
fd.readlines()已经读到文件尾部了,然后while循环中fd.readline()肯定还是尾部,不跳出才怪了。。。
在"while 1:"前面加一句“fd.seek(0)”,可以重置文件指针为文件开头。


   

论坛徽章:
0
4 [报告]
发表于 2013-09-05 13:51 |只看该作者
第一,你既然已经readlines了为什么不把最后一行放入变量?
第二,你可以用seek跳转到文件末尾

论坛徽章:
0
5 [报告]
发表于 2013-09-05 14:50 |只看该作者
谢谢3、4楼,找到了我问题的原因,谢谢

论坛徽章:
11
技术图书徽章
日期:2014-03-01 14:44:34天蝎座
日期:2014-05-21 22:11:59金牛座
日期:2014-05-30 17:06:14
6 [报告]
发表于 2013-09-05 17:40 |只看该作者
回复 5# lzzfriend
看你提到文件可能会比较大,那么fd.readlines()就不太合适,它会把整个文件读入内存并生成list,这是爆内存的节奏。我这里有个内存占用相对可控的demo
  1. #!/usr/bin/env python
  2. import os
  3. import sys

  4. def get_last_n_lines(logfile, n):
  5.     blk_size_max = 4096
  6.     n_lines = []
  7.     with open(logfile, 'rb') as fp:
  8.         fp.seek(0, os.SEEK_END)
  9.         cur_pos = fp.tell()
  10.         while cur_pos > 0 and len(n_lines) < n:
  11.             blk_size = min(blk_size_max, cur_pos)
  12.             fp.seek(cur_pos - blk_size, os.SEEK_SET)
  13.             blk_data = fp.read(blk_size)
  14.             assert len(blk_data) == blk_size
  15.             lines = blk_data.split('\n')

  16.             # adjust cur_pos
  17.             if len(lines) > 1 and len(lines[0]) > 0:
  18.                 n_lines[0:0] = lines[1:]
  19.                 cur_pos -= (blk_size - len(lines[0]))
  20.             else:
  21.                 n_lines[0:0] = lines
  22.                 cur_pos -= blk_size
  23.             fp.seek(cur_pos, os.SEEK_SET)

  24.     if len(n_lines) > 0 and len(n_lines[-1]) == 0:
  25.         del n_lines[-1]
  26.     return n_lines[-n:]

  27. def main():
  28.     if len(sys.argv) != 3:
  29.         sys.exit('usage: %s logfile n_lines' % sys.argv[0])
  30.     for line in get_last_n_lines(sys.argv[1], int(sys.argv[2])):
  31.         print line

  32. if __name__ == '__main__':
  33.     main()
复制代码
注:
1. 不用读取整个文件,从文件尾部开始,以4KiB为一个Block向前迭代,直到取到指定的行数,这里假设你只关心后面若干行,内存占用不大。
2. 如果日志文件是动态增长的,而且写日志的程序和分析日志的程序没有做进程间同步,那么就要考虑一点解析日志的容错性,比如某次读取的最后一行是不完整的。合理的处理方式应该是每次最多读取最后两行,如果最后一行格式不对,应该取倒数第二行。

   

论坛徽章:
11
技术图书徽章
日期:2014-03-01 14:44:34天蝎座
日期:2014-05-21 22:11:59金牛座
日期:2014-05-30 17:06:14
7 [报告]
发表于 2013-09-05 17:58 |只看该作者
如果不执着于Python实现,拿subprocess调用shell的tail最简单了。。。

论坛徽章:
0
8 [报告]
发表于 2013-09-06 15:20 |只看该作者
调用shell命令快捷方便。

论坛徽章:
2
酉鸡
日期:2014-02-19 09:11:08摩羯座
日期:2014-05-23 10:16:16
9 [报告]
发表于 2013-09-13 10:33 |只看该作者
本帖最后由 tiankafeiwu 于 2013-09-13 10:33 编辑

那为什么不直接fd.seek(linecount-2)呢?然后在fd.readline()回复 3# timespace


   

论坛徽章:
0
10 [报告]
发表于 2013-09-14 11:58 |只看该作者
我也是习惯用shell,下面是取得CPU温度的代码(FB系统):
  1. #!/usr/local/bin/python

  2. import commands

  3. cmd="sysctl -a | grep hw.acpi.thermal.tz0.temperature"
  4. agv=0.0
  5. for a in range(4):
  6.         (t,tmp)=commands.getstatusoutput(cmd)
  7.         t=tmp.split(':')
  8.         tmp=t[1].split('.')
  9.         agv=agv+int(tmp[0])
  10. print  agv//4
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP