Я пишу программу, которая будет периодически анализировать файл журнала 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()))