python 模拟 linux shell 下的 tail -f 动态打印日志
博客专区 > xrzs 的博客 > 博客详情
python 模拟 linux shell 下的 tail -f 动态打印日志
xrzs 发表于4年前
python 模拟 linux shell 下的 tail -f 动态打印日志
  • 发表于 4年前
  • 阅读 4100
  • 收藏 11
  • 点赞 0
  • 评论 8

腾讯云 技术升级10大核心产品年终让利>>>   

linux shell 下有个  tail 命令可以方便的动态打印、输出日志,这对根据程序日志调试来说相当方便。

在 python 下怎么实现呢?主要思路其实也不难:先跳到文件末尾,然后不断的打印出新行,直到文件结束,然后再更新指针位置,最后再死循环重复上述过程即可。恰巧 github 上看到一份不错的代码,贴过来,以备忘。

1、代码:

#!/usr/bin/env python

'''
Python-Tail - Unix tail follow implementation in Python.

python-tail can be used to monitor changes to a file.

Example:
    import tail

    # Create a tail instance
    t = tail.Tail('file-to-be-followed')

    # Register a callback function to be called when a new line is found in the followed file.
    # If no callback function is registerd, new lines would be printed to standard out.
    t.register_callback(callback_function)

    # Follow the file with 5 seconds as sleep time between iterations.
    # If sleep time is not provided 1 second is used as the default time.
    t.follow(s=5) '''

# Author - Kasun Herath <kasunh01 at gmail.com>
# Source - https://github.com/kasun/python-tail

import os
import sys
import time

class Tail(object):
    ''' Represents a tail command. '''
    def __init__(self, tailed_file):
        ''' Initiate a Tail instance.
            Check for file validity, assigns callback function to standard out.

            Arguments:
                tailed_file - File to be followed. '''
        self.check_file_validity(tailed_file)
        self.tailed_file = tailed_file
        self.callback = sys.stdout.write

    def follow(self, s=1):
        ''' Do a tail follow. If a callback function is registered it is called with every new line.
        Else printed to standard out.

        Arguments:
            s - Number of seconds to wait between each iteration; Defaults to 1. '''

        with open(self.tailed_file) as file_:
            # Go to the end of file
            file_.seek(0,2)
            while True:
                curr_position = file_.tell()
                line = file_.readline()
                if not line:
                    file_.seek(curr_position)
                else:
                    self.callback(line)
                time.sleep(s)

    def register_callback(self, func):
        ''' Overrides default callback function to provided function. '''
        self.callback = func

    def check_file_validity(self, file_):
        ''' Check whether the a given file exists, readable and is a file '''
        if not os.access(file_, os.F_OK):
            raise TailError("File '%s' does not exist" % (file_))
        if not os.access(file_, os.R_OK):
            raise TailError("File '%s' not readable" % (file_))
        if os.path.isdir(file_):
            raise TailError("File '%s' is a directory" % (file_))

class TailError(Exception):
    def __init__(self, msg):
        self.message = msg
    def __str__(self):
        return self.message

2、测试数据:

在 shell 下执行如下语句,会每秒更新一个数据到 a.txt 中。

while : ; do echo $((i++)) >> a.txt ; sleep 1; done

3、测试代码:

import tail

'''
python-tail example.
Does a tail follow against /var/log/syslog with a time interval of 5 seconds.
Prints recieved new lines to standard out
'''

def print_line(txt):
    ''' Prints received text '''
    print(txt)

# Create a tail instance
t = tail.Tail(r'C:\Users\june\Desktop\a.txt')

# Register a callback function to be called when a new line is found in the followed file.
# If no callback function is registerd, new lines would be printed to standard out.
t.register_callback(print_line)

# Follow the file with 2 seconds as sleep time between iterations.
# If sleep time is not provided 1 second is used as the default time.
t.follow(s=2)

Refer:

[1] python-tail/tail.py

http://https://github.com/wojons/python-tail/blob/master/tail.py

[2] Re: 请教如何用Python实现类似于shell的tail -f filename的功能?

http://markmail.org/message/mcaepjfpe7y3hrak

[3] "tail -f" with inode monitor (Python recipe)

http://code.activestate.com/recipes/577398-tail-f-with-inode-monitor/

[4] python连接scribe收集apache日志

http://blog.csdn.net/jiedushi/article/details/7968152#0-tsina-1-32830-397232819ff9a47a7b7e80a40613cfe1

共有 人打赏支持
粉丝 1408
博文 520
码字总数 339422
评论 (8)
CoderAres
感觉没有任何意义,系统都已经有该功能了。
xrzs

引用来自“CoderAres”的评论

感觉没有任何意义,系统都已经有该功能了。

你说的结论不是我转载此文的目的,如果你只盯着这个功能来看,那确实,没必要往下看了。
颓废的幻想者
seek 指针 是按照字符来的吧。 当处理大量数据 超过上千万行 的日志 不会影响效率么
go-skyblue
挺好
我lei个去

引用来自“myjack”的评论

seek 指针 是按照字符来的吧。 当处理大量数据 超过上千万行 的日志 不会影响效率么

亲测,读取一百万行的日志文件运行无压力。日志是每秒输出10行。

zhujinhe
这个按照默认只输出2秒钟后的最后一行而不是2秒钟内的所有变化,而且只能监视一个文件。其中有一个人fork了一个项目,改善了这一情况。https://github.com/wojons/python-tail
xrzs

引用来自“zhujinhe”的评论

这个按照默认只输出2秒钟后的最后一行而不是2秒钟内的所有变化,而且只能监视一个文件。其中有一个人fork了一个项目,改善了这一情况。https://github.com/wojons/python-tail
_Kelly
赞。用于自动构建,实用
×
xrzs
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: