为了账号安全,请及时绑定邮箱和手机立即绑定

请问如何在Python中跟踪日志文件?

/ 猿问

请问如何在Python中跟踪日志文件?

守候你守候我 2019-10-21 16:12:22

如何在Python中跟踪日志文件?

我希望在Python中可以在没有阻塞或锁定的情况下使用tail-F或类似的输出。我找到了一些很老的代码这里,但我想现在肯定有更好的方法或图书馆来做同样的事情了。有人听说过吗?

理想情况下,我会有tail.getNewData()每次我想要更多数据的时候我都可以打电话给你。



查看完整描述

3 回答

?
浮云间

非阻塞

如果您在Linux上(因为windows不支持调用SELECT文件),您可以使用子进程模块和SELECT模块。

import timeimport subprocessimport select

f = subprocess.Popen(['tail','-F',filename],\
        stdout=subprocess.PIPE,stderr=subprocess.PIPE)p = select.poll()p.register(f.stdout)while True:
    if p.poll(1):
        print f.stdout.readline()
    time.sleep(1)

这将轮询输出管道中的新数据,并在可用时将其打印出来。通常time.sleep(1)print f.stdout.readline()将被有用的代码所取代。

阻塞

您可以使用子流程模块,而无需额外的SELECT模块调用。

import subprocess
f = subprocess.Popen(['tail','-F',filename],\
        stdout=subprocess.PIPE,stderr=subprocess.PIPE)while True:
    line = f.stdout.readline()
    print line

这也会在添加新行时打印出新行,但是它将阻塞直到尾程序关闭,可能使用f.kill().



查看完整回答
反对 回复 2019-10-22
?
一只萌萌小番薯

使用SH模块(PIP安装sh):

from sh import tail# runs foreverfor line in tail("-f", "/var/log/some_log_file.log", _iter=True):
    print(line)

[最新情况]

因为.尾巴和._iter=True是一个生成器,您可以:

import sh
tail = sh.tail("-f", "/var/log/some_log_file.log", _iter=True)

然后,您可以使用以下方法“getNewData”:

new_data = tail.next()

请注意,如果尾缓冲区是空的,它将阻塞直到有更多的数据(从您的问题,它不清楚您想做什么,在这种情况下)。

[最新情况]

如果将-f替换为-f,这是可行的,但是在Python中,它将是锁定的。如果有可能的话,我会更感兴趣的是,如果可能的话,我可以调用一个函数来获取我想要的新数据。-伊莱

容器生成器将尾调用放置在一个时间真循环中,并捕获最终的I/O异常,其效果与-F几乎相同。

def tail_F(some_file):
    while True:
        try:
            for line in sh.tail("-f", some_file, _iter=True):
                yield line        except sh.ErrorReturnCode_1:
            yield None

如果无法访问该文件,生成器将不返回任何。但是,如果文件是可访问的,它仍然会阻塞,直到有新的数据为止。我还不清楚你在这件事上想做什么。

雷蒙德·赫廷格的做法似乎相当不错:

def tail_F(some_file):
    first_call = True
    while True:
        try:
            with open(some_file) as input:
                if first_call:
                    input.seek(0, 2)
                    first_call = False
                latest_data = input.read()
                while True:
                    if '\n' not in latest_data:
                        latest_data += input.read()
                        if '\n' not in latest_data:
                            yield ''
                            if not os.path.isfile(some_file):
                                break
                            continue
                    latest_lines = latest_data.split('\n')
                    if latest_data[-1] != '\n':
                        latest_data = latest_lines[-1]
                    else:
                        latest_data = input.read()
                    for line in latest_lines[:-1]:
                        yield line + '\n'
        except IOError:
            yield ''

如果文件无法访问或没有新数据,此生成器将返回“。

[最新情况]

最后一个答案的第二个绕到文件的顶部,它似乎在数据耗尽的时候出现。-伊莱

我认为当尾过程结束时,第二行将输出最后十行,-f每当出现I/O错误时。这个tail --follow --retry在大多数情况下,我可以在类似Unix的环境中考虑到行为。

也许,如果你更新你的问题来解释你真正的目标是什么(你为什么想模仿尾巴-重试),你会得到一个更好的答案。

最后一个答案实际上不是跟随尾巴,只是读取运行时可用的内容。-伊莱

当然,在默认情况下,尾巴会显示最后10行.您可以使用file.find定位文件末尾的文件指针,我将留给读者一个适当的实现作为练习。

与基于子进程的解决方案相比,IMHO的file.read()方法要优雅得多。



查看完整回答
反对 回复 2019-10-22
?
慕仰8121524

唯一便携路子tail -f实际上,文件似乎是从它读取并重试(在sleep)如果read返回0。这个tail各种平台上的实用程序使用特定于平台的技巧(例如:kqueue(关于BSD)可以永远有效地跟踪文件,而不需要sleep.

因此,实施一个好的tail -f纯粹使用Python可能不是一个好主意,因为您必须使用最小的公分母实现(而不求助于特定于平台的黑客)。使用一个简单的subprocess打开tail -f在单独的线程中迭代行,可以很容易地实现非阻塞。tail在Python中进行操作。

实例实现:

import threading, Queue, subprocess
tailq = Queue.Queue(maxsize=10) # buffer at most 100 linesdef tail_forever(fn):
    p = subprocess.Popen(["tail", "-f", fn], stdout=subprocess.PIPE)
    while 1:
        line = p.stdout.readline()
        tailq.put(line)
        if not line:
            breakthreading.Thread(target=tail_forever, args=(fn,)).start()print tailq.get()
             # blocksprint tailq.get_nowait() # throws Queue.Empty if there are no lines to read



查看完整回答
反对 回复 2019-10-22

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信