如何实现与 tail -F 等效的 Python 代码?

2025-03-12 08:54:00
admin
原创
32
摘要:问题描述:观察一个不断增长的文件尾部是否存在某些关键字的 Python 方式是什么?在 shell 中我可能会说:tail -f "$file" | grep "$string" | while read hit; do #stuff done 解决方案 1:嗯...

问题描述:

观察一个不断增长的文件尾部是否存在某些关键字的 Python 方式是什么?

在 shell 中我可能会说:

tail -f "$file" | grep "$string" | while read hit; do
    #stuff
done

解决方案 1:

嗯,最简单的方法就是不断地从文件中读取内容,检查有什么新内容,并测试是否命中。

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:

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_matches 保存在配置文件中,以便可以将其用于多种用途。我的增强功能列表包括对正则表达式的支持,而不是简单的“in”匹配。

解决方案 3:

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

要么打开文件O_NONBLOCK,要么使用它select来轮询读取可用性,然后read读取新数据和字符串方法来过滤文件末尾的行...或者只是使用subprocess模块并让tailgrep为您完成工作,就像在 shell 中一样。

解决方案 4:

您可以使用 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:

看起来有一个这样的包:https://github.com/kasun/python-tail

解决方案 6:

如果您无法将问题限制为基于行的读取,则需要借助于块。

这应该有效:

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

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

解决方案 7:

以下代码:

  • 适用于Linux

  • 用途inotify

  • 不需要第三方库

  • 使用ctypes

import os
import ctypes
import ctypes.util

# Constants for inotify
IN_MODIFY = 0x00000002

# Load libc
libc = ctypes.CDLL(ctypes.util.find_library('c'))

# Define inotify functions from libc
inotify_init = libc.inotify_init
inotify_add_watch = libc.inotify_add_watch
inotify_read = libc.read

# Define the tail_file function
def tail_file(filepath):
    # Initialize inotify
    inotify_fd = inotify_init()

    # Add a watch for file modification events
    wd = inotify_add_watch(inotify_fd, filepath.encode(), IN_MODIFY)

    # Open the file and move to the end
    with open(filepath, 'r') as file:
        file.seek(0, os.SEEK_END)

        while True:
            # Create a buffer to store inotify events
            buffer = os.read(inotify_fd, 1024)  # This will block until the file is modified

            # Read and print any new lines from the file
            line = file.readline()
            if line:
                print(line, end='')

tail_file('your_file.txt')

解决方案 8:

据我所知,Python 函数列表中没有与“tail”等效的函数。解决方案是使用 tell()(获取文件大小)和 read() 来计算结束行。

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

解决方案 9:

您可以使用pytailf:简单的 python tail -f 包装器

from tailf import tailf    

for line in tailf("myfile.log"):
    print line

解决方案 10:

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

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

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

解决方案 11:

您可以使用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 的一种简洁的方法。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1887  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1425  
  在制造业数字化转型的进程中,PLM(产品生命周期管理)系统、ERP(企业资源计划)系统、MES(制造执行系统)以及 CAD(计算机辅助设计)软件都扮演着至关重要的角色。然而,这些系统和软件各自独立运行时,往往难以发挥出最大的协同效应。实现 PLM 系统与 ERP、MES、CAD 的有效集成,成为提升企业整体竞争力、优化...
plm系统的主要功能模块   3  
  产品生命周期管理(PLM)作为一种先进的管理理念和技术,在电子与半导体行业正发挥着日益重要的作用。随着电子与半导体行业的快速发展,产品更新换代速度加快,市场竞争愈发激烈,企业面临着诸多挑战,如缩短产品上市时间、提高产品质量、降低成本等。而PLM的应用为企业应对这些挑战提供了有效的解决方案,展现出巨大的应用价值。提升产品...
plm项目   4  
  PLM(产品生命周期管理)项目管理软件在现代企业的产品研发、生产与运营中扮演着至关重要的角色。它整合了从产品概念设计到退役的全流程数据与流程,助力企业提升效率、降低成本并增强创新能力。随着科技的飞速发展以及企业需求的不断演变,未来十年 PLM 项目管理软件的发展充满了无限可能,值得深入探讨与预测。智能化与自动化趋势智能...
plm产品全生命周期管理   6  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用