Python, читающий только конец огромного текстового файла
Возможный дубликат:
Получить последние n строк файла с Python, похожие на хвост
Прочитайте файл в обратном порядке с помощью python
У меня есть файл размером около 15 ГБ, это файл журнала, из которого я должен анализировать вывод. Я уже делал базовый синтаксический анализ аналогичного, но БОЛЬШОГО меньшего файла, с несколькими строками ведения журнала. Строки анализа - это не проблема. Проблема заключается в огромном файле и количестве избыточных данных, которые он содержит.
В основном я пытаюсь сделать python script, что я могу сказать; например, дайте мне 5000 последних строк файла. Это опять-таки основная обработка аргументов и все такое, ничего особенного там, я могу это сделать.
Но как определить или сообщить читателю файла ТОЛЬКО прочитать количество строк, которые я указал в конце файла? Я пытаюсь пропустить huuuuuuuge количество строк в начале файла, так как я не заинтересован в этих и, честно говоря, чтение около 15 ГБ строк из txt файла занимает слишком много времени. Есть ли способ ошибиться. Начните читать с конца файла? Это даже имеет смысл?
Все сводится к проблеме чтения 15-гигабайтного файла, строка за строкой занимает слишком много времени. Поэтому я хочу пропустить уже избыточные данные (по крайней мере, избыточно для меня) и только читать количество строк из конца файла, который я хочу прочитать.
Очевидный ответ заключается в том, чтобы вручную просто скопировать N количество строк из файла в другой файл, но есть ли способ сделать это полуавтоматически, только чтобы прочитать N количество строк из конца файла с помощью python?
Ответы
Ответ 1
Вам нужно найти конец файла, а затем прочитать фрагменты в блоках с конца, подсчитывая строки, пока не найдете достаточно строк для чтения строк n
.
В принципе, вы повторно реализуете простую форму хвоста.
Вот немного слегка проверенный код, который делает именно это:
import os, errno
def lastlines(hugefile, n, bsize=2048):
# get newlines type, open in universal mode to find it
with open(hugefile, 'rU') as hfile:
if not hfile.readline():
return # empty, no point
sep = hfile.newlines # After reading a line, python gives us this
assert isinstance(sep, str), 'multiple newline types found, aborting'
# find a suitable seek position in binary mode
with open(hugefile, 'rb') as hfile:
hfile.seek(0, os.SEEK_END)
linecount = 0
pos = 0
while linecount <= n + 1:
# read at least n lines + 1 more; we need to skip a partial line later on
try:
hfile.seek(-bsize, os.SEEK_CUR) # go backwards
linecount += hfile.read(bsize).count(sep) # count newlines
hfile.seek(-bsize, os.SEEK_CUR) # go back again
except IOError, e:
if e.errno == errno.EINVAL:
# Attempted to seek past the start, can't go further
bsize = hfile.tell()
hfile.seek(0, os.SEEK_SET)
linecount += hfile.read(bsize).count(sep)
break
raise # Some other I/O exception, re-raise
pos = hfile.tell()
# Re-open in text mode
with open(hugefile, 'r') as hfile:
hfile.seek(pos, os.SEEK_SET) # our file position from above
for line in hfile:
# We've located n lines *or more*, so skip if needed
if linecount > n:
linecount -= 1
continue
# The rest we yield
yield line
Ответ 2
Подтвердите это для unix:
import os
os.popen('tail -n 1000 filepath').read()
используйте subprocess.Popen вместо os.popen, если вам нужно иметь доступ к stderr (и некоторым другим функциям)
Ответ 3
Хотя я бы предпочел решение "хвост" - если вы знаете максимальное количество символов в строке, вы можете реализовать другое возможное решение, получив размер файла, откройте обработчик файла и используйте метод "искать" с помощью определенное количество символов, которое вы ищете.
Этот заключительный код должен выглядеть так: просто объясните, почему я также предпочитаю хвостовое решение:) goodluck!
MAX_CHARS_PER_LINE = 80
size_of_file = os.path.getsize('15gbfile.txt')
file_handler = file.open('15gbfile.txt', "rb")
seek_index = size_of_file - (number_of_requested_lines * MAX_CHARS_PER_LINE)
file_handler.seek(seek_index)
buffer = file_handler.read()
вы можете улучшить этот код, проанализировав новые строки буфера, который вы читаете.
Удачи (и вы должны использовать хвостовое решение;-) Я уверен, что вы можете получить хвост для каждой ОС.
Ответ 4
Предпочтительным методом в этот момент было просто использовать хвост unix для задания и модифицировать питон для принятия ввода через вход std.
tail hugefile.txt -n1000 | python magic.py
Ничего сексуального, но по крайней мере он заботится о работе. Я обнаружил, что большой файл слишком большой нагрузки для обработки. По крайней мере, для моих навыков питона. Так что было намного проще просто добавить к нему щепотку магии nix, чтобы сократить размер файла. Хвост был для меня новым. Узнал что-то и выяснил другой способ снова использовать терминал в моих интересах. Всем спасибо.