使用Python实时读取正在写入的日志文件

74 投票
5 回答
88826 浏览
提问于 2025-04-16 01:34

我想用Python找到一个好的方法,实时读取一个日志文件。我希望能逐行处理这个日志文件里的内容,等到文件写入的时候再开始读取。为了做到这一点,我需要不断尝试读取这个文件,直到它被创建,然后继续处理里面的内容,直到我手动停止这个过程。

有没有合适的方法可以做到这一点呢?

5 个回答

8

因为这是关于Python和日志记录的内容,所以还有另一种方法可以做到这一点。

我假设你是在使用Python的日志记录器,也就是基于logging.Handler的。

你可以创建一个类,获取一个(命名的)日志实例,然后重写它的emit函数,把日志信息显示到图形界面上。如果你还需要在控制台显示,只需给文件处理器添加一个控制台处理器就可以了。

举个例子:

import logging

class log_viewer(logging.Handler):
    """ Class to redistribute python logging data """

    # have a class member to store the existing logger
    logger_instance = logging.getLogger("SomeNameOfYourExistingLogger")

    def __init__(self, *args, **kwargs):
         # Initialize the Handler
         logging.Handler.__init__(self, *args)

         # optional take format
         # setFormatter function is derived from logging.Handler 
         for key, value in kwargs.items():
             if "{}".format(key) == "format":
                 self.setFormatter(value)

         # make the logger send data to this class
         self.logger_instance.addHandler(self)

    def emit(self, record):
        """ Overload of logging.Handler method """

        record = self.format(record)

        # ---------------------------------------
        # Now you can send it to a GUI or similar
        # "Do work" starts here.
        # ---------------------------------------

        # just as an example what e.g. a console
        # handler would do:
        print(record)

我现在使用类似的代码来添加一个TkinterTreectrl.Multilistbox,以便在运行时查看日志输出。

顺便提一下:日志记录器只有在初始化后才能获取数据,所以如果你想要所有的数据可用,就需要在一开始就初始化它。(我知道这是预期的,但我觉得提一下还是有必要的。)

63

看看这个PDF文档,链接在这里:this PDF,从第38页开始,大约在第77张幻灯片,你会找到你需要的所有信息。当然,其他的幻灯片也很精彩,但这些特别和你的问题有关:

import time
def follow(thefile):
    thefile.seek(0,2) # Go to the end of the file
    while True:
        line = thefile.readline()
        if not line:
            time.sleep(0.1) # Sleep briefly
            continue
        yield line
34

你可以试试这样的代码:

import time

while 1:
    where = file.tell()
    line = file.readline()
    if not line:
        time.sleep(1)
        file.seek(where)
    else:
        print line, # already has newline

这个例子是从 这里 提取的。

撰写回答