Python - Как открыть файл и указать смещение в байтах?

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

Проблема в том, что я не хочу открывать данные журнала и анализа, которые я уже проанализировал. Например:

line1
line2
line3

Если я проанализирую этот файл, я сохраню все строки, а затем сохраню это смещение. Таким образом, когда я снова разбираю его, я получаю:

line1
line2
line3 - The log will open from this point
line4
line5

Во второй раз, я получу line4 и line5. Надеюсь, это имеет смысл...

Что мне нужно знать, как это сделать? Python имеет функцию seek(), чтобы указать смещение... Так что просто я могу получить размер файла журнала (в байтах) после его разбора, а затем использовать его как смещение (в поиске()) во второй раз, когда я его запишу?

Я не могу представить себе способ кодирования этого > . <

Ответ 1

Вы можете управлять позицией в файле благодаря методам seek и tell класса file, см. http://docs.python.org/library/stdtypes.html#file-objects

Метод tell расскажет вам, где искать в следующий раз, когда вы открываете

Ответ 2

log = open('myfile.log')
pos = open('pos.dat','w')
print log.readline()
pos.write(str(f.tell())
log.close()
pos.close()

log = open('myfile.log')
pos = open('pos.dat')
log.seek(int(pos.readline()))
print log.readline()

Конечно, вы не должны использовать его так: вы должны обернуть операции вверх в таких функциях, как save_position(myfile) и load_position(myfile), но функциональность там есть.

Ответ 3

Если ваши лог файлы легко вписываются в память (у вас есть разумная политика ротации), вы можете легко сделать что-то вроде:

log_lines = open('logfile','r').readlines()
last_line = get_last_lineprocessed() #From some persistent storage
last_line = parse_log(log_lines[last_line:])
store_last_lineprocessed(last_line)

Если вы не можете этого сделать, вы можете использовать что-то вроде этого (см. принятое использование ответа поиска и указать, если вам нужно сделать это с ними) Получить последние n строк файл с Python, похожий на хвост

Ответ 4

Если вы анализируете строку журнала на строку, вы можете просто сохранить номер строки из последнего разбора. Тогда вы должны были бы начать читать его с хорошей строки в следующий раз.

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

Ответ 5

Легко, но не рекомендуется:):

last_line_processed = get_last_line_processed()    
with open('file.log') as log
    for record_number, record in enumerate(log):
        if record_number >= last_line_processed:
            parse_log(record)

Ответ 6

Обратите внимание, что вы можете искать() в python с конца файла:

f.seek(-3, os.SEEK_END)

помещает позицию чтения 3 строки из EOF.

Однако почему бы не использовать diff, либо из оболочки, либо с помощью difflib?

Ответ 7

Вот код, подтверждающий использование вашего sugestion и tell metond:

beginning="""line1
line2
line3"""

end="""- The log will open from this point
line4
line5"""

openfile= open('log.txt','w')
openfile.write(beginning)
endstarts=openfile.tell()
openfile.close()

open('log.txt','a').write(end)
print open('log.txt').read()

print("\nAgain:")
end2 = open('log.txt','r')
end2.seek(len(beginning))

print end2.read()  ## wrong by two too little because of magic newlines in Windows
end2.seek(endstarts)

print "\nOk in Windows also"
print end2.read()
end2.close()

Ответ 8

Вот эффективный и безопасный сниппет, чтобы сохранить это смещение, прочитанное в параллельном файле. В основном logtail в python.

with open(filename) as log_fd:
    offset_filename = os.path.join(OFFSET_ROOT_DIR,filename)
    if not os.path.exists(offset_filename):
        os.makedirs(os.path.dirname(offset_filename))
        with open(offset_filename, 'w') as offset_fd:
            offset_fd.write(str(0))
    with open(offset_filename, 'r+') as offset_fd:
        log_fd.seek(int(offset_fd.readline()) or 0)
        new_logrows_handler(log_fd.readlines())
        offset_fd.seek(0)
        offset_fd.write(str(log_fd.tell()))