Удалить последнюю строку в файле python
Высокоуровневый язык программирования Python 3 предоставляет своим пользователям массу полезных средств для взаимодействия с текстовыми файлами. Встроенные методы платформы позволяют не только создавать документы для хранения строковой информации, но и читать из них данные, а также записывать, удалять и всячески манипулировать их содержимым.
Создание, открытие и закрытие файла
Работа с любым текстовым файлом в Python начинается с вызова специальной функции open, которая принимает в качестве параметров путь к объекту на компьютере и режим обработки. Путь к документу можно указать как абсолютный (адрес расположения на жестком диске ПК), так и как относительный (координаты относительно папки проекта). Выбирая нужный режим обработки файла, следует учитывать его назначение (“w” для записи, “r” для чтения данных). Следующий пример показывает простое взаимодействие с текстовым документом.
Как можно заметить, функция open принимает относительный путь файла и открывает его для записи. Если в папке с исходным кодом документа с аналогичным именем и расширением .txt не существует, метод open создает его самостоятельно, после чего открывает для него нужный режим обработки. Выполнив все необходимые действия с переменной file, которая ссылается на реальный файл, следует вручную закрыть его, чтобы избежать потери информации. Данную задачу выполняет метод close, если вызвать его при помощи оператора доступа (точки).
Выполнить точно такие же действия, но без необходимости вручную закрывать файл, вполне возможно благодаря связке операторов with as. Для этого необходимо поместить метод open сразу после ключевого слова with, а переменную, которая будет ссылаться на файл, прописать за конструкцией as. Ниже располагается пример открытия документа с помощью with as.
Оба примера небольших программ демонстрируют работу с test.txt, который генерируется в каталоге с исходным кодом. В качестве режима обработки для него выбирается запись данных. После этого при помощи метода write в него заносится строка “hello world”. Завершается код в обоих случаях закрытием текстового файла test.txt методом close или автоматически.
Запись построчно
Чтобы быстро записать информацию в текстовый файл, достаточно открыть его в программе, написанной на языке Python, после чего воспользоваться функцией write через переменную, которая ссылается на документ.
Приведенный выше пример небольшой программы показывает создание небольшого массива lines, который содержит три строковых элемента: “first”, “second” и “third”. За счет функции open и связки операторов with as происходит открытие текстового файла test.txt в корневом каталоге жесткого диска D. В цикле мы проходим по всем элементам списка и с помощью команды write их записываем. Чтобы каждая запись была с новой строки, добавляем символ перевода строки.
Так же можно воспользоваться функцией writelines. Если мы передадим в качестве ее параметра список, то она запишет элементы друг за другом в одну строку. Но можно поступить следующим образом: в качестве параметра передать генератор следующим образом.
Этот пример отличается от предыдущего тем, что вызывается метод writelines, который принимает в качестве аргумента генератор. Для разделения элементов последовательности тут применяется “\n”, благодаря чему каждое слово в документе будет находиться в отдельной строке.
Чтение построчно
Прочитать содержимое текстового файла построчно в языке Python очень просто, поскольку в этом прекрасно помогает цикл for. Но для начала все же необходимо открыть документ, как и в предыдущем случае, при помощи open и with as. Однако на этот раз следует указать другой режим обработки файла, выбрав для него “r” для получения доступа к чтению данных.
В этом примере показывается открытие файла test.txt, в котором уже содержится небольшой массив строк, записанный ранее. Построчное чтение информации из файла производится в цикле for. Каждая итерация выводит сведения из новой строки (line) при помощи функции print. Все элементы отображаются на экране построчно, как и были ранее помещены в test.txt.
Количество строк
Возможности языка Python позволяют производить и куда более сложные виды программных операций с внутренним содержимым текстовых файлов. Например, если требуется определить в Python количество строк в файле, можно открыть файл и в цикле посчитать количество занятых в нем строк. В этом поможет предварительно объявленная переменная count, в которую перед применением нужно записать 0, а затем прибавлять по единице с каждой новой строкой.
Приведенный выше пример демонстрирует работу счетчика count. Для взаимодействия с ним следует открыть текстовый файл в режиме чтения, а затем инкрементировать в каждом новом шаге цикла for объявленную ранее числовую переменную, которая затем выводится в print.
Можно поступить и другим способом. Прочитать файл в список с помощью readlines. А после этого с помощью функции len определить размер списка. Это и будет количество строк.
Поиск строки
Чтобы с помощью Python найти строку в текстовом файле, стоит прибегнуть к помощи встроенного метода readlines, который позволяет автоматически считывать внутреннее содержимое файла. Как и раньше, для начала необходимо открыть test.txt для чтения, чтобы затем поместить данные из него в специальный массив lines. Встроенный метод index позволяет найти номер элемента в последовательности, просто передав ему нужный объект, например, строку “second”.
Поскольку в test.txt все элементы располагаются в отдельных строках, к строке, которую стоит передать методу index в качестве аргумента, необходимо прибавить конструкцию “\n”.
Удаление строки
Чтобы в Python удалить ненужную строку из файла, следует воспользоваться сразу двумя режимами обработки файлов: чтение и запись. Для начала необходимо открыть test.txt для чтения, чтобы поместить информацию из него в отдельный массив lines. Далее потребуется удалить один из элементов последовательности при помощи оператора del, указав ему индекс нужной строки в квадратных скобках. Массив объектов, который получился в итоге, необходимо поместить в исходный текстовый файл, однако на этот раз открыть его надо в режиме записи.
Приведенный выше пример небольшой программы демонстрирует удаление строки из файла. В данном случае используются методы readlines и writelines, позволяющие считывать массив строк из документа и записывать его туда же, разделяя отдельные элементы списка.
Обратите внимание, что в приведенном примере удалится вторая строка, так как индексы списка считаются от нулевого элемента.Таким образом, можно достаточно легко взаимодействовать с содержимым текстовых файлов, пользуясь языком программирования Python 3. Его встроенные функции позволяют записывать данные в документ и считывать их в удобном для пользователя виде. При помощи средств по расширенной работе с файлами, можно управлять ими на куда более продвинутом уровне.
Скажем, у меня есть текстовый файл, полный псевдонимов, как я могу удалить определенный псевдоним из этого файла?
Попробуйте fileinput , как описано @j-f-sebastian JF-Себастьяне здесь . Это , кажется, позволяет вам строку за строкой работать через временный файл, все с простой for синтаксиса.Предполагая, что ваш файл находится в формате одного псевдонима для каждой строки, используйте это.
Сначала откройте файл:
Далее, получите все ваши строки из файла:
Теперь вы можете закрыть файл:
И снова откройте его в режиме записи:
Затем запишите строки, кроме строки, которую вы хотите удалить. Возможно, вы захотите изменить "\n" на любую строку, заканчивающую использование вашего файла.
В конце закройте файл еще раз.
@Ooker: Вы должны открыть файл дважды (и закрыть его между), потому что в первом режиме он «только для чтения», потому что вы просто читаете текущие строки в файле. Затем вы закрываете его и снова открываете в «режиме записи», где файл доступен для записи, и вы заменяете содержимое файла без строки, которую хотите удалить. Почему Python не позволяет нам сделать это в одну строку? @Ooker, когда вы читаете строку, попробуйте представить курсор, движущийся вдоль линии, когда она читается. Как только эта строка была прочитана, курсор теперь проходит мимо нее. Когда вы пытаетесь записать в файл, вы пишете, где курсор находится в данный момент. Повторно открывая файл, вы сбрасываете курсор. Я не знал, что это так сложно. Спасибо. Если у нас есть функция курсора сброса, значит ли это, что нам не нужно закрывать и снова открывать ее? @Waddas Почему бы просто не переместить курсор? Это кажется ненужным сложным для меня.Решение этой проблемы только с одним открытым:
Это решение открывает файл в режиме r/w ( "r +" ) и использует поиск reset f-указателя, а затем усекает, чтобы удалить все после последней записи.
Это сработало очень хорошо для меня, так как я должен был также использовать lockfile (fcntl). Я не мог найти способ использовать fileinput вместе с fcntl. Было бы неплохо увидеть некоторые побочные эффекты этого решения. Я бы не стал этого делать. Если вы получите ошибку в цикле for , вы получите частично перезаписанный файл с дублированными строками или отрезанной строкой. Вы можете захотеть использовать f.truncate() сразу после f.seek(0) . Таким образом, если вы получите ошибку, вы просто получите неполный файл. Но реальное решение (если у вас есть место на диске) - вывести во временный файл, а затем использовать os.replace() или pathlib.Path(temp_filename).replace(original_filename) чтобы заменить его оригиналом после того, как все успешно выполнено.Самый лучший и быстрый вариант, а не сохранение всего в списке и повторное открытие файла для его записи, на мой взгляд, переписать файл в другом месте.
Что это! В одном цикле и один вы можете сделать то же самое. Это будет намного быстрее.
Вместо использования обычного цикла for мы можем использовать выражение генератора. Таким образом, программа не будет загружать все строки из файла в память, что не является хорошей идеей в случае больших файлов. Он будет иметь только одну строку в памяти за раз. С генератором выражение для цикла будет выглядеть так: (output.write(line) for line in input if line!="nickname_to_delete"+"\n") @ShriShinde Вы не читаете файл в память, когда зацикливаетесь на объекте файла, поэтому это решение работает идентично вашему предложению. os.replace (новинка в python v 3.3) является более кроссплатформенным, чем системный вызов mv .Проблема с чтением строк в первом проходе и внесением изменений (удаление определенных строк) во втором проходе заключается в том, что если размеры файлов огромны, у вас закончится ОЗУ. Вместо этого лучший подход состоит в том, чтобы читать строки один за другим и записывать их в отдельный файл, исключая те, которые вам не нужны. Я использовал этот подход с файлами размером до 12-50 ГБ, а использование ОЗУ остается практически неизменным. Только циклы ЦП показывают, что процесс обработки продолжается.
Это "fork" основано на решении, представленном @Lother здесь, которое, я считаю, следует считать правильным ответом.
Для файла с таким содержимым:
Эта вилка от решения Lother работает нормально:
Основным преимуществом является использование with open , которые отбрасывают использование f.close() , а также способ, которым script оценивает, содержит ли строка строку.
@yifan Да, да. В противном случае вместо перезаписи файла вы добавляете файл к себе (без исключаемых строк).Не удастся решить, если вы поместили целый файл в память, я знаю, что в наши дни у всех есть тонны памяти, но подумайте, есть ли в файле несколько ГБ журналов или что-то в этом роде.
Лучше всего скопировать его по строкам в новый файл, чем удалить первый или что-то подобное
Я думаю, что если вы прочитаете файл в списке, то сделайте так, чтобы вы могли перебирать список, чтобы искать прозвище, от которого вы хотите избавиться. Вы можете сделать это очень эффективно, не создавая дополнительные файлы, но вам придется записать результат обратно в исходный файл.
Вот как я могу это сделать:
Я предполагаю, что nicknames.csv содержит такие данные, как:
Затем загрузите файл в список:
Затем перейдите к списку в соответствии с вашими входом для удаления:
Наконец, запишите результат в файл:
Если вы используете Linux, вы можете попробовать следующий подход.
Предположим, у вас есть текстовый файл с именем animal.txt :
Удалить первую строку:
Это решение не зависит от ОС, и, поскольку OP не указывал операционную систему, нет никаких причин размещать специфический для Linux ответ imo. Любой, кто предлагает использовать подпроцесс для всего, что может быть сделано с помощью всего лишь python, получает отрицательный ответ! И +1 к @SteinarLima. Я согласенВ общем, вы не можете; вам нужно снова написать весь файл (по крайней мере, с точки зрения изменения до конца).
В некоторых конкретных случаях вы можете сделать лучше, чем это -
если все ваши элементы данных имеют одинаковую длину и не имеют определенного порядка, и вы знаете смещение того, с которым хотите избавиться, вы можете скопировать последний элемент над тем, который нужно удалить, и обрезать файл до последний элемент;
или вы можете просто перезаписать блок данных значением "это плохие данные, пропустить" или сохранить флаг "этот элемент был удален" в ваших сохраненных элементах данных, чтобы вы могли пометить его, не изменяя при этом файл.
Это, вероятно, слишком много для коротких документов (что-то под 100 КБ?).
Я создал следующий код, чтобы найти количество строк в файле, но я не знаю, как удалить указанный номер строки. Я новичок в python - так что если есть более простой способ - скажите, пожалуйста.
EDIT:
Вы можете использовать вышеуказанный код, а затем: -
Это даст вам массив строк, содержащих все строки, но последний.
Поскольку я регулярно работаю со многими гигабайтными файлами, цикл, как упоминалось в ответах, не работает для меня. Решение, которое я использую:
Это не использует python, но python - неправильный инструмент для задания, если это единственная задача, которую вы хотите. Вы можете использовать стандартную утилиту * nix head и запустить
который скопирует все, кроме последней строки имени файла, в новый файл.
Предполагая, что вам нужно сделать это на Python, и что у вас достаточно большой файл, список разрезов которого недостаточен, вы можете сделать это за один проход по файлу:
Не самый элегантный код в мире, но он выполняет свою работу.
В основном он буферизует каждую строку в файле через переменную last_line, каждая итерация выводит предыдущую строку итераций.
В системах, где file.truncate() работает, вы можете сделать что-то вроде этого:
Согласно моим тестам, file.tell() не работает при чтении по строке, по-видимому, из-за буферизации, запутывающей его. Вот почему это добавляет длины линий для определения позиций. Обратите внимание, что это работает только в системах, где разделитель строк заканчивается на "\n".
Хотя я не тестировал его (пожалуйста, не ненавидите это), я считаю, что есть более быстрый способ его перевести. Это скорее решение C, но вполне возможно в Python. Это тоже не Pythonic. Это теория, я бы сказал.
Во-первых, вам нужно знать кодировку файла. Установите переменную в число байтов, в котором используется символ (1 байт в ASCII). CHARsize (почему бы и нет). Вероятно, будет 1 байт с файлом ASCII.
Затем возьмите размер файла, установите для него FILEsize.
Предположим, что у вас есть адрес файла (в памяти) в FILEadd.
Добавьте FILEsize в FILEadd.
Переместить назад слова (приращение на -1 *** CHARsize **), тестирование каждого байта CHARsize для \n (или любой новой строки, используемой вашей системой). Когда вы достигнете первого \n, теперь у вас есть позиция начала первой строки файла. Замените \n на\x1a (26, ASCII для EOF или что-то другое, что является вашей системой/с кодировкой).
Очистите, однако, вам нужно (изменить размер файла, коснуться файла).
Если это работает так, как я подозреваю, это позволит вам сэкономить много времени, так как вам не нужно читать весь файл с самого начала, вы читаете его с конца.
Вы можете использовать модуль fileinput для обновления файла - обратите внимание, что это приведет к удалению всех строк, содержащих фразу:
Пользователь по имени gnibbler разместил что-то похожее на это в другом потоке.
Если другую программу можно изменить для вывода файлового набора вместо номера строки, вы можете напрямую назначить смещение на p и обойтись без цикла цикла
Я нашел другое решение, которое работает эффективно и обойдется без выполнения всего нечистого и не очень элегантного подсчета строк в файловом объекте:
Подробное объяснение для тех, кто этого хочет:
(2) Откройте текстовый файл и поместите его в файл-объект. На данный момент нужен только режим чтения. Затем поместите его содержимое в список:
(3) Теперь каждая строка должна быть проиндексированным элементом в "списке". Вы можете продолжить, удалив элемент, представляющий строку, которую вы хотите удалить:
В этот момент, если вы получили строку no. который должен быть удален из пользовательского ввода, обязательно сначала преобразуйте его в целое число, так как оно будет в формате строки наиболее вероятно (если вы использовали "input()" ).
Это del_line - 1, потому что индекс элемента списка начинается с 0. Однако я предполагаю, что вы (или пользователь) начинаете считать "1" для строки №. 1, и в этом случае вам нужно вычесть 1, чтобы поймать правильный элемент в списке.
(4) Откройте файл списка еще раз, на этот раз в "режиме записи", переписав полный файл. После этого перейдите по обновленному списку, переписав каждый элемент "списка" в файл. Вам не нужно беспокоиться о новых строках, потому что в настоящий момент вы помещаете содержимое исходного файла в список (шаг 2),\n экраны также будут скопированы в элементы списка:
Это выполнило эту работу для меня, когда я хотел, чтобы пользователь решил, какую строку удалить в определенном текстовом файле. Я думаю, что ответ Martijn Pieters делает sth. похоже, однако его объяснение мало для меня, чтобы я мог сказать.
Читайте также: