代码之家  ›  专栏  ›  技术社区  ›  pra

如何实现Python中tail-F的等价物?

  •  30
  • pra  · 技术社区  · 16 年前

    tail -f "$file" | grep "$string" | while read hit; do
        #stuff
    done
    
    10 回复  |  直到 16 年前
        1
  •  29
  •   dbr    16 年前

    好吧,最简单的方法是不断地从文件中读取,检查新内容并测试点击率。

    import time
    
    def watch(fn, words):
        fp = open(fn, 'r')
        while True:
            new = fp.readline()
            # Once all lines are read this just returns ''
            # until the file changes and a new line appears
    
            if new:
                for word in words:
                    if word in new:
                        yield (word, new)
            else:
                time.sleep(0.5)
    
    fn = 'test.py'
    words = ['word']
    for hit_word, hit_sentence in watch(fn, words):
        print "Found %r in line: %r" % (hit_word, hit_sentence)
    

    此解决方案具有 readline 如果你知道你的数据会以行的形式出现,那么它就有效了。

    word 您正在寻找,请先填写。这样就有点复杂了。..

        2
  •  6
  •   user166278    16 年前
    def tail(f):
        f.seek(0, 2)
    
        while True:
            line = f.readline()
    
            if not line:
                time.sleep(0.1)
                continue
    
            yield line
    
    def process_matches(matchtext):
        while True:
            line = (yield)  
            if matchtext in line:
                do_something_useful() # email alert, etc.
    
    
    list_of_matches = ['ERROR', 'CRITICAL']
    matches = [process_matches(string_match) for string_match in list_of_matches]    
    
    for m in matches: # prime matches
        m.next()
    
    while True:
        auditlog = tail( open(log_file_to_monitor) )
        for line in auditlog:
            for m in matches:
                m.send(line)
    

    我用它来监视日志文件。在完整的实现中,我将list_of_matchs保存在一个配置文件中,这样它就可以用于多种目的。在我的增强列表中,支持正则表达式,而不是简单的“in”匹配。

        3
  •  4
  •   Corey Porter    16 年前

    编辑:正如下面的评论所指出的, O_NONBLOCK 不适用于磁盘上的文件。如果其他人来寻找来自套接字、命名管道或其他进程的尾部数据,这仍然会有所帮助,但 没有回答实际提出的问题 原始答案如下。(调用tail和grep是可行的,但无论如何都是一种非答案。)

    用以下方式打开文件 O_noblock 和使用 select read 读取新数据,并使用字符串方法过滤文件末尾的行。..或者只是使用 subprocess 模块和let tail grep

        4
  •  4
  •   Walter Mundt    12 年前

    您可以使用select来轮询文件中的新内容。

    def tail(filename, bufsize = 1024):
        fds = [ os.open(filename, os.O_RDONLY) ]
        while True:
            reads, _, _ = select.select(fds, [], [])
            if 0 < len(reads):
                yield os.read(reads[0], bufsize)
    
        5
  •  3
  •   kommradHomer    11 年前
        6
  •  2
  •   tobych    13 年前

    您可以使用 pytailf

    from tailf import tailf    
    
    for line in tailf("myfile.log"):
        print line
    
        7
  •  1
  •   deets    16 年前

    如果你不能将问题约束为基于行的读取,你需要求助于块。

    这应该奏效:

    import sys
    
    needle = "needle"
    
    blocks = []
    
    inf = sys.stdin
    
    if len(sys.argv) == 2:
        inf = open(sys.argv[1])
    
    while True:
        block = inf.read()
        blocks.append(block)
        if len(blocks) >= 2:
            data = "".join((blocks[-2], blocks[-1]))
        else:
            data = blocks[-1]
    
        # attention, this needs to be changed if you are interested
        # in *all* matches separately, not if there was any match ata all
        if needle in data:
            print "found"
            blocks = []
        blocks[:-2] = []
    
        if block == "":
            break
    

    挑战在于确保您匹配针,即使它被两个块边界隔开。

        8
  •  0
  •   Zoe Adams Zoe Adams    16 年前

    这篇博客文章(不是我写的)有写出来的功能,看起来很适合我! http://www.manugarg.com/2007/04/real-tailing-in-python.html

        9
  •  0
  •   James    9 年前

    如果你只需要一个非常简单的Python 3解决方案来处理文本文件的行,而不需要Windows支持,这对我来说很有效:

    import subprocess
    def tailf(filename):
        #returns lines from a file, starting from the beginning
        command = "tail -n +1 -F " + filename
        p = subprocess.Popen(command.split(), stdout=subprocess.PIPE, universal_newlines=True)
        for line in p.stdout:
            yield line
    for line in tailf("logfile"):
        #do stuff
    

    它阻止了等待新行写入,因此如果不进行一些修改,这不适合异步使用。

        10
  •  -2
  •   FogleBird    16 年前

    您可以使用 collections.deque 实现尾部。

    http://docs.python.org/library/collections.html#deque-recipes ...

    def tail(filename, n=10):
        'Return the last n lines of a file'
        return deque(open(filename), n)
    

    当然,这会读取整个文件内容,但这是实现tail的一种简洁明了的方式。

    推荐文章