Подтвердить что ты не робот

Чтение из часто обновляемого файла

В настоящее время я пишу программу на python в системе Linux. Цель состоит в том, чтобы прочитать файл журнала и выполнить команду bash при поиске определенной строки. Файл журнала постоянно записывается другой программой. Мой вопрос:

Если я открою файл с помощью метода open(), мой файл Python будет обновлен, так как фактический файл будет записан другой программой или мне придется повторно открыть файл с временными интервалами?

Спасибо

Джим

UPDATE: Спасибо за ответы. Возможно, я должен был упомянуть, что файл записывается с помощью приложения Java EE, поэтому я не могу контролировать, когда на него записываются данные. В настоящее время у меня есть программа, которая разворачивает файл каждые 10 секунд и пытается прочитать из позиции байта в файле, который последний раз читал. На данный момент он просто распечатывает возвращаемую строку. Я надеялся, что файл не нужно будет открывать повторно, но команда чтения каким-то образом будет иметь доступ к данным, записанным в файл приложением Java.

#!/usr/bin/python
import time

fileBytePos = 0
while True:
    inFile = open('./server.log','r')
    inFile.seek(fileBytePos)
    data = inFile.read()
    print data
    fileBytePos = inFile.tell()
    print fileBytePos
    inFile.close()
    time.sleep(10)

Спасибо за советы по pyinotify и генераторам. Я собираюсь посмотреть на них для лучшего решения.

4b9b3361

Ответ 1

Я бы рекомендовал посмотреть на David Beazley Generator Tricks для Python, особенно Часть 5: Обработка бесконечных данных. Он будет обрабатывать эквивалент Python команды tail -f logfile в режиме реального времени.

# follow.py
#
# Follow a file like tail -f.

import time
def follow(thefile):
    thefile.seek(0,2)
    while True:
        line = thefile.readline()
        if not line:
            time.sleep(0.1)
            continue
        yield line

if __name__ == '__main__':
    logfile = open("run/foo/access-log","r")
    loglines = follow(logfile)
    for line in loglines:
        print line,

Ответ 2

"Интерактивный сеанс стоит 1000 слов"

>>> f1 = open("bla.txt", "wt")
>>> f2 = open("bla.txt", "rt")
>>> f1.write("bleh")
>>> f2.read()
''
>>> f1.flush()
>>> f2.read()
'bleh'
>>> f1.write("blargh")
>>> f1.flush()
>>> f2.read()
'blargh'

Другими словами - да, будет один "открытый".

Ответ 3

Поскольку вы ориентируетесь на систему Linux, вы можете использовать pyinotify, чтобы уведомить вас об изменении файла.

Там также этот трюк, который может сработать для вас. Он использует file.seek для выполнения tail -f.

Ответ 4

Вот немного измененная версия ответа Jeff Bauer, которая устойчива к усечению файлов. Очень полезно, если ваш файл обрабатывается logrotate.

import os
import time

def follow(name):
    current = open(name, "r")
    curino = os.fstat(current.fileno()).st_ino
    while True:
        while True:
            line = current.readline()
            if not line:
                break
            yield line

        try:
            if os.stat(name).st_ino != curino:
                new = open(name, "r")
                current.close()
                current = new
                curino = os.fstat(current.fileno()).st_ino
                continue
        except IOError:
            pass
        time.sleep(1)


if __name__ == '__main__':
    fname = "test.log"
    for l in follow(fname):
        print "LINE: {}".format(l)

Ответ 5

Я не эксперт здесь, но я думаю, вам придется использовать какой-то шаблон наблюдателя, чтобы пассивно наблюдать за файлом, а затем запускать событие, которое снова открывает файл, когда происходит изменение. Что касается того, как на самом деле реализовать это, я понятия не имею.

Я не думаю, что open() откроет файл в реальном времени, как вы предлагаете.

Ответ 6

Если у вас есть код, читающий файл, работающий в цикле while:

f = open('/tmp/workfile', 'r')
while(1):
    line = f.readline()
    if line.find("ONE") != -1:
        print "Got it"

и вы пишете тот же файл (в режиме добавления) из другой программы. Как только в файл добавится "ONE", вы получите распечатку. Вы можете предпринять любые действия, которые вы хотите предпринять. Короче говоря, вам не нужно повторно открывать файл через регулярные промежутки времени.

>>> f = open('/tmp/workfile', 'a')
>>> f.write("One\n")
>>> f.close()
>>> f = open('/tmp/workfile', 'a')
>>> f.write("ONE\n")
>>> f.close()