Получить последние n строк файла с Python, похожего на tail
Я пишу средство просмотра файлов журнала для веб-приложения и для этого хочу разбивать страницы по строкам файла журнала. Элементы в файле основаны на строках с новейшим элементом внизу.
Мне нужен метод tail() , который может читать строки n снизу и поддерживает смещение. То, что я придумал, выглядит так:
Это разумный подход? Каков рекомендуемый способ хвостать файлы журналов со смещениями?
29 ответов
Код, который я закончил, использовал. Я думаю, что это самое лучшее:
Это может быть быстрее вашего. Не делает предположений о длине строки. Обрабатывает файл по одному блоку за раз, пока не найдет нужное количество символов «\n».
Мне не нравятся сложные предположения о длине строки, когда — как практическое дело — вы никогда не можете знать такие вещи.
Как правило, это будет определять последние 20 строк на первом или втором проходе через цикл. Если ваша вещь с 74 символами на самом деле точна, вы делаете размер блока 2048, и вы почти сразу закроете 20 строк.
Кроме того, я не сжигаю много мозговых калорий, пытаясь увязнуть с физическими блоками ОС. Используя эти высокоуровневые пакеты ввода-вывода, я сомневаюсь, что вы увидите какое-либо влияние производительности на попытку выравнивания по границам блоков ОС. Если вы используете ввод-вывод нижнего уровня, вы можете увидеть ускорение.
Предполагается Unix-подобная система на Python 2, которую вы можете сделать:
Для Python 3 вы можете сделать:
Если чтение всего файла приемлемо, используйте deque.
До 2.6 у deques не было опции maxlen, но ее было достаточно легко реализовать.
Если это требование для чтения файла с конца, то используйте поиск по галопу (a.k.a экспоненциальный).
Ответ С.Лотта выше почти работает для меня, но в итоге дает мне частичные строки. Оказывается, это повреждает данные на границах блоков, потому что данные хранят прочитанные блоки в обратном порядке. Когда вызывается ‘.join (данные), блоки расположены в неправильном порядке. Это исправляет это.
Вот мой ответ. Чистый питон. Использование timeit кажется довольно быстрым. Хвост 100 строк файла журнала, который имеет 100 000 строк:
Простое и быстрое решение с mmap:
Еще более чистая версия, совместимая с Python3, которая не вставляет, а добавляет и переворачивает:
используйте это так:
Публикация ответа от моего комментария на аналогичный вопрос, где тот же метод использовался для изменения последней строки файла, а не просто для его получения.
Для файла значительного размера mmap — лучший способ сделать это. Чтобы улучшить существующий ответ mmap , эта версия переносима между Windows и Linux и должна работать быстрее (хотя она не будет работать без некоторых модификаций 32-битного Python с файлами в диапазоне ГБ, см. Другой ответ для подсказок по обработке). это и для модификации для работы на Python 2).
Предполагается, что число выровненных строк достаточно мало, и вы можете безопасно прочитать их все в память одновременно; Вы также можете сделать это функцией генератора и вручную прочитать строку за раз, заменив последнюю строку на:
Наконец, это читается в двоичном режиме (необходимо использовать mmap ), поэтому он дает строки str (Py2) и строки bytes (Py3); если вы хотите использовать unicode (Py2) или str (Py3), итеративный подход может быть изменен для вас и/или исправления новых строк:
Примечание: я напечатал все это на машине, где у меня нет доступа к Python для тестирования. Пожалуйста, дайте мне знать, если я что-то опечатал; это было достаточно похоже на мой другой ответ, что я думаю, что это должно работать, но изменения (например, обработка offset ) могут привести к незначительным ошибкам. Пожалуйста, дайте мне знать в комментариях, если есть какие-либо ошибки.
Python-сообщество
Собственно столкнулся с сабжем. Для парсера нужно читать последнюю строку из файла, что бы можно было продолжить работу сто старого места. Файл большой 15 — 20 кк строк.
Дядя Гугл сказал, что встроенного метода решения проблемы — нет:
— Либо прочитать весь файл readlines и взять последнюю строку (быстро, но всю память съест ).
— Либо пробежать весь файл xreadlines и опять таки взять последнюю строку (память останется целой, но каждый раз ждать пока переберется весь файл).
Короче — не один вариант не подходит. Пришлось идти самым примитивным путем, перебирать каждый символ с конца файла и при совпадении его с символом конца строки — выводить. Но код у меня получился страшноватый:) Может кто подправит или расскажет как он делает?
#2 Ноя. 24, 2010 16:03:44
Быстрый способ прочитать последнюю строку в файле
Вполне нормальный код. Думаю, достаточно будет сделать из него функцию.
#3 Ноя. 24, 2010 17:44:24
Быстрый способ прочитать последнюю строку в файле
🙂
Лучше читать блоками, а не по одному байту.
Зачем перечитывать строку, которую уже считал?
Вариации на тему:
#4 Ноя. 24, 2010 21:52:39
Быстрый способ прочитать последнюю строку в файле
#5 Ноя. 25, 2010 13:11:25
Быстрый способ прочитать последнюю строку в файле
Вот мой вариант. По-моему элегантно =D
PS Предыдущие свои сообщения удалил, чтобы не засорять эфир 🙂
Отредактировано (Ноя. 25, 2010 13:18:50)
#6 Ноя. 26, 2010 01:57:37
Быстрый способ прочитать последнюю строку в файле
#7 Ноя. 26, 2010 08:59:53
Быстрый способ прочитать последнюю строку в файле
Каков подлец! =D Спасибо за замечание
#8 Ноя. 26, 2010 17:38:03
Быстрый способ прочитать последнюю строку в файле
Такая задача часто встречается во всяких логах. Файл длинный сообщений много, но их круг ограничен. Решить задачу значительно проще если сделать дополнительные предположения. В данном случае можно декларировать что длина строки не более MAX_ROW. Тогда будет еще красивее и эффективнее
Отредактировано (Ноя. 26, 2010 17:38:53)
#9 Ноя. 26, 2010 22:54:33
Быстрый способ прочитать последнюю строку в файле
Из документации к seek: If the file is opened in text mode (without ‘b’), only offsets returned by tell() are legal. Use of other offsets causes undefined behavior.
Дословно: Если файл открыт в текстовом режиме (без ‘b’), правомерны только отступы, возвращаемые tell(). Использование прочих отступов вызывает неопределенное поведение.
Какая-то мутная фраза, но уж точно не эквивалентна seek для текстовых файлов дает непредсказуемый результат . Или у вас другой текст? Можно ссылку?
Смотрим tell: Return the file’s current position, like stdio‘s ftell().
Смотрим stdio‘s ftell() (в GNU libc): This function can fail if the stream doesn’t support file positioning, or if the file position can’t be represented in a long int, and possibly for other reasons as well. If a failure occurs, a value of -1 is returned.
Мой вывод: поведение не определено в случае, если отступ превышает long int в С-компиляторе, на котором собран Ваш python.
#10 Ноя. 26, 2010 23:06:52
Быстрый способ прочитать последнюю строку в файле
Несмотря на то, что файл открыт в символьном режиме seek и tell оперируют байтовыми смещениями.
Рассмотрим следующую ситуацию: файл в utf-8 с русскими буквами и переводом строки в unix стиле.
В этом случае можно “прыгать” только на начала символов. Т.е. если содержимое файла начинается с
то правильные позиции сначала будут четными. Затем идет ‘\n’ — 1 байт. И снова двухбайтные символы.
Попытка позиционироваться внутрь символа собьет к чертям все что можно — так делать нельзя.
И угадать в общем случае невозможно — как я показал выше, длина символа может меняться.
Поэтому прыгать можно только на ранее полученные позиции.
Как прочитать последнюю строку и дописать данные
Имеются большие файлы от 5мб и выше, к примеру 1 файл содержит 114320 строк.
Необходимо считать последнюю или предпоследнюю строку (если в последней был символ новой строки), и дописать новые данные. Видел разные реализации, но все они предполагают, что файл будет маленький.
![]()
![]()
Чтобы прочитать последнюю строку в относительно небольшом файле:
Большой файл можно с конца читать пока новая строка не встретится, используя mmap :
Этот вариант возвращает байты и не поддерживает режим универсальных строк. Пример:
Для чтения пары строк с конца, ещё может подойти, к примеру, tail(file, n) функция из @A. Coady ответа. Размер буфера в ответе удваивается по схожей причине, описанной в Непонятное замедление конкатенации в цикле — при чтении с конца нужно быть осторожным, чтобы не сделать ваш алгоритм квадратичным случайно:
Сравните производительность (включая deque() вариант), чтобы узнать какое решение лучше работает в вашем случае.
Как прочитать последнюю строку файла в Python?
Первое требование . Я хочу прочитать последнюю строку файла и присвоить последнее значение переменной в Python.
Второе требование —
Вот мой пример файла.
Из этого файла я хочу прочитать содержимое, например filename.txt , которое будет после <context:property-placeholder location= . . И хочу присвоить это значение переменной в python.
8 ответов
Простое решение, которое не требует сохранения всего файла в памяти (например, с помощью file.readlines() или аналогичной конструкции):
Для больших файлов было бы более эффективно искать до конца файла и двигаться назад, чтобы найти новую строку, например:
Обратите внимание, что файл должен быть открыт в двоичном режиме, иначе будет невозможно искать с конца.
Почему бы вам просто не прочитать все строки и не сохранить последнюю строку в переменной?
В системах, где есть команда tail , вы можете использовать tail , что для больших файлов избавит вас от необходимости читать файл целиком.
Примечание: команда decode() требуется только для python3
Подойдет для python2.x
Вы можете прочитать и отредактировать всю строку, сделав что-то вроде:
Он не просто спрашивает, как читать строки в файле или как читать последнюю строку в переменной. Он также спрашивает, как разобрать подстроку из последней строки, содержащую его целевое значение.
Вот один способ. Это самый короткий путь? Нет, но если вы не знаете, как нарезать строки, вам следует начать с изучения каждой встроенной функции, используемой здесь. Этот код получит то, что вы хотите:
Вывод команды печати должен выглядеть так:
Темы, затронутые здесь:
- Чтение текстовых файлов
- Составление списка Python строк из содержимого, чтобы упростить получение последней строки с использованием индекса len(List) -1 с отсчетом от нуля.
- Использование find для получения позиций индекса строки внутри строки
- Использование slice для получения подстрок
Все эти темы находятся в документации Python — здесь нет ничего лишнего, и импорт не требуется для использования встроенных функций, которые здесь использовались.
Обобщается для чтения строки с N-й до последней
Как говорили многие другие люди, для больших файлов любой подход, не стремящийся к концу или иным образом не начинающийся с конца файла, очень неэффективен. Тем не менее, подход к поиску верхнего ответа великолепен. Если кто-то еще ищет решение, которое вместо этого читает от n до последней строки файла, вот одно, которое я написал. Также очень быстро и эффективно для больших файлов (взял под мс для файла 7гб по сети).
Выполните проверку размера и выполните поиск назад на определенное количество байтов от конца файла, если он содержит по крайней мере такое количество байтов: