python高性能的实现tail -n 功能

2018-12-14  本文已影响0人  王炎杰

最近有一个项目需要去读取日志文件的后面几行 ,但不想去直接调用linux系统自带的tail。这样太没有挑战性了。

于是自己动手写了一个。

参考了 https://www.jianshu.com/p/d5c7f16687bd。这篇文章中的实现。但该实现在文件行较长,行数较多的情况下会有非常严重的性能问题。所以我动手改进了代码。

代码判断行数是用的找已读取的字符串中的“\n”的数目。
这个实现的好处之一是不需要重复读文件。当然,行较长较多时也会消耗比较大的内存。
这个实现是肯定比不上系统自己的。但它毕竟是我自己写的。

# coding:utf-8
# coding:utf-8
import argparse

__author__ = 'bary'

"""
2018年12月14日 19时00分
"""

PAGE = 4096

parser = argparse.ArgumentParser(description="")
parser.add_argument("-n", "--number", default=5, help="", type=int)
parser.add_argument("-f", "--file", default="/var/log/jiankong.log", help="")


def tail(line, src):
    """性能较好,虽然还是比linux自带的tail慢很多 囧 """
    buf = []
    with open(src, "rb") as f:
        f.seek(0, 2)
        f_len = f.tell()
        now = f_len
        a_num_n = 0
        while 1:
            if now - PAGE >= 0:
                n_read = PAGE
            else:
                n_read = now
            seek_n = (f_len - now) + n_read
            f.seek(-seek_n, 2)
            temp = f.read(n_read)
            buf.append(temp)
            a_num_n += temp.count("\n")
            if a_num_n - 1 >= line or now <= PAGE:
                buf.reverse()
                return ''.join(buf).splitlines()[-line:]
            else:
                now -= PAGE
                f.seek(-seek_n, 2)


if __name__ == "__main__":
    args = parser.parse_args()

    for i in tail(args.number, args.file):
        print i

本文作者: 王炎杰
本文链接:https://www.jianshu.com/p/fb632c63e444
版权声明: 转载请注明出处!

上一篇下一篇

猜你喜欢

热点阅读