Попробуйте , fileinputкак описано @ JF-Себастьяне здесь . Похоже, что вы можете работать построчно, через временный файл, с простым forсинтаксисом.
Кевин
Ответы:
205
Сначала откройте файл и получите все свои строки из файла. Затем снова откройте файл в режиме записи и запишите свои строки обратно, за исключением строки, которую вы хотите удалить:
with open("yourfile.txt","r")as f:
lines = f.readlines()with open("yourfile.txt","w")as f:for line in lines:if line.strip("\n")!="nickname_to_delete":
f.write(line)
Вам нужно strip("\n")использовать символ новой строки в сравнении, потому что если ваш файл не заканчивается символом новой строки, то и последний lineне будет.
почему мы должны открывать и закрывать его дважды?
Ooker
3
@Ooker: Вы должны открыть файл дважды (и закрыть его между ними), потому что в первом режиме он «только для чтения», потому что вы просто читаете текущие строки в файле. Затем вы закрываете его и снова открываете в «режиме записи», где файл доступен для записи, и вы заменяете содержимое файла без строки, которую хотите удалить.
Девин
4
Почему Python не позволяет нам сделать это в одну строку?
Ooker
5
@Ooker, когда вы читаете строку, попробуйте представить курсор, движущийся вдоль строки, когда она читается. Как только эта строка была прочитана, курсор теперь проходит мимо нее. Когда вы пытаетесь записать в файл, вы пишете, где курсор находится в данный момент. При повторном открытии файла вы сбрасываете курсор.
Ваддас
4
Пьют с соединением!
Sceluswe 20.09.16
101
Решение этой проблемы только с одним открытием:
with open("target.txt","r+")as f:
d = f.readlines()
f.seek(0)for i in d:if i !="line you want to remove...":
f.write(i)
f.truncate()
Это решение открывает файл в режиме r / w («r +») и использует поиск, чтобы сбросить f-указатель, а затем усечь, чтобы удалить все после последней записи.
Это сработало очень хорошо для меня, так как я должен был также использовать lockfile (fcntl). Я не мог найти способ использовать fileinput вместе с fcntl.
Easyrider
1
Было бы неплохо увидеть некоторые побочные эффекты этого решения.
user1767754
3
Я бы не стал этого делать. Если вы получите ошибку в forцикле, вы получите частично перезаписанный файл с дублирующимися линиями или половиной обрезанной строки. Возможно, вы захотите f.truncate()сразу после f.seek(0)этого. Таким образом, если вы получите ошибку, вы просто получите неполный файл. Но реальное решение (если у вас есть место на диске) - вывести во временный файл, а затем использовать os.replace()или pathlib.Path(temp_filename).replace(original_filename)заменить его оригиналом после того, как все будет успешно.
Борис
Можете ли вы добавить, i.strip('\n') != "line you want to remove..."как указано в принятом ответе, это прекрасно решило бы мою проблему. Потому что просто iничего не сделал для меня
Mangohero1
31
Лучший и самый быстрый вариант, вместо того, чтобы хранить все в списке и заново открывать файл, чтобы записать его, - по моему мнению, переписать файл в другом месте.
with open("yourfile.txt","r")as input:with open("newfile.txt","w")as output:for line in input:if line.strip("\n")!="nickname_to_delete":
output.write(line)
Это оно! В одном цикле и только один вы можете сделать то же самое. Это будет намного быстрее.
Вместо использования обычного цикла for мы можем использовать выражение генератора. Таким образом, программа не будет загружать все строки из файла в память, что не является хорошей идеей в случае больших файлов. Он будет иметь только одну строку в памяти одновременно. С генератором выражение для цикла будет выглядеть так:(output.write(line) for line in input if line!="nickname_to_delete"+"\n")
shrishinde 25.02.16
4
@ShriShinde Вы не читаете файл в память, когда зацикливаетесь на объекте файла, поэтому это решение работает идентично вашему предложению.
Стейнар Лима
Возможно, вы захотите удалить исходный файл и переименовать второй файл с именем исходного файла, которое с Python на ОС Linux будет выглядеть следующим образом,subprocess.call(['mv', 'newfile.txt', 'yourfile.txt'])
Max
6
os.replace(новинка в python v 3.3) более кроссплатформенная, чем системный вызов mv.
7yl4r
Просто и замечательно.
JuBaer AD
27
Это "вилка" от @Lother (который, я считаю, следует считать правильным ответом).
Для такого файла:
$ cat file.txt
1: october rust
2: november rain
3: december snow
Эта вилка из решения Лотера отлично работает:
#!/usr/bin/python3.4with open("file.txt","r+")as f:
new_f = f.readlines()
f.seek(0)for line in new_f:if"snow"notin line:
f.write(line)
f.truncate()
Улучшения:
with open, которые отказываются от использования f.close()
более понятным if/elseдля оценки, если строка не присутствует в текущей строке
@ Да, да. В противном случае вместо перезаписи файла вы добавляете файл к себе (без исключаемых строк).
Борис
5
Проблема с чтением строк на первом проходе и внесением изменений (удалением определенных строк) на втором проходе заключается в том, что если у вас большие размеры файлов, вам не хватит ОЗУ. Вместо этого, лучший подход - читать строки по одной и записывать их в отдельный файл, исключая ненужные. Я использовал этот подход для файлов размером 12-50 ГБ, и использование оперативной памяти остается практически постоянным. Только циклы процессора показывают обработку в процессе.
Это решение не зависит от ОС, и, поскольку OP не указывал операционную систему, нет никаких причин размещать специфический для Linux ответ imo.
Стейнар Лима
2
Любой, кто предлагает использовать подпроцесс для всего, что может быть сделано с помощью всего лишь python, получает отрицательный ответ! И +1 к @SteinarLima ... Я согласен
Джейми Линдси
2
Я думаю, что если вы прочитаете файл в список, то выполните итерацию по списку, чтобы найти псевдоним, от которого вы хотите избавиться. Вы можете сделать это очень эффективно, не создавая дополнительные файлы, но вам придется записать результат обратно в исходный файл.
Вот как я могу это сделать:
import, os, csv # and other imports you need
nicknames_to_delete =['Nick','Stephen','Mark']
Я предполагаю, nicknames.csvсодержит данные, такие как:
Далее, переходим к списку, чтобы соответствовать вашим входам для удаления:
for nick in nicknames_to_delete:try:if nick in nicknames:
nicknames.pop(nicknames.index(nick))else:print(nick +" is not found in the file")exceptValueError:pass
Наконец, запишите результат обратно в файл:
with open("nicknames.csv","a")as nicknamesFile:
nicknamesFile.seek(0)
nicknamesFile.truncate()
nicknamesWriter = csv.writer(nicknamesFile)for name in nicknames:
nicknamesWriter.writeRow([str(name)])
nicknamesFile.close()
В общем, вы не можете; Вы должны написать весь файл снова (по крайней мере, с момента изменения до конца).
В некоторых конкретных случаях вы можете сделать лучше, чем это -
если все ваши элементы данных имеют одинаковую длину и не в определенном порядке, и вы знаете смещение того, от которого хотите избавиться, вы можете скопировать последний элемент поверх того, который нужно удалить, и обрезать файл до последнего элемента ;
или вы можете просто перезаписать блок данных значением «это плохие данные, пропустить его» или оставить флаг «этот элемент был удален» в ваших сохраненных элементах данных, чтобы вы могли пометить его как удаленный, не изменяя файл другим способом.
Это, вероятно, излишне для коротких документов (что-нибудь под 100 КБ?).
Возможно, вы уже получили правильный ответ, но здесь мой. Вместо того, чтобы использовать список для сбора нефильтрованных данных (что readlines()делает метод), я использую два файла. Один предназначен для хранения основных данных, а второй - для фильтрации данных при удалении определенной строки. Вот код:
main_file = open('data_base.txt').read()# your main dataBase file
filter_file = open('filter_base.txt','w')
filter_file.write(main_file)
filter_file.close()
main_file = open('data_base.txt','w')for line in open('filter_base'):if'your data to delete'notin line:# remove a specific string
main_file.write(line)# put all strings back to your db except deletedelse:pass
main_file.close()
Сохраните строки файла в списке, затем удалите из списка строку, которую хотите удалить, и запишите оставшиеся строки в новый файл.
with open("file_name.txt","r")as f:
lines = f.readlines()
lines.remove("Line you want to delete\n")with open("new_file.txt","w")as new_f:for line in lines:
new_f.write(line)
Если ваш файл не заканчивается новой строкой, этот код не удалит последнюю строку, даже если он содержит слово, которое вы хотите удалить.
Борис
0
Вот еще один способ удалить некоторые строки из файла:
src_file = zzzz.txt
f = open(src_file,"r")
contents = f.readlines()
f.close()
contents.pop(idx)# remove the line item from list, by line number, starts from 0
f = open(src_file,"w")
contents ="".join(contents)
f.write(contents)
f.close()
Предполагая, что вы можете загрузить свой полный текстовый файл. Затем вы определяете список нежелательных псевдонимов, а затем заменяете их пустой строкой "".
# Delete unwanted charactersimport re
# Read, then decode for py2 compat.
path_to_file ='data/nicknames.txt'
text = open(path_to_file,'rb').read().decode(encoding='utf-8')# Define unwanted nicknames and substitute them
unwanted_nickname_list =['SourDough']
text = re.sub("|".join(unwanted_nickname_list),"", text)
нет необходимости строить диктовку, просто используйтеfor nb, line in enumerate(f.readlines())
Дионис
-3
Возьмите содержимое файла, разбейте его на новую строку в кортеж. Затем получите доступ к номеру строки вашего кортежа, присоедините его к кортежу результата и перезапишите файл.
(1) ты имеешь в виду tuple(f.read().split('\n'))?? (2) «получить доступ к номеру строки вашего кортежа» и «присоединиться к вашему кортежу результата» звучит довольно загадочно; Фактический код Python может быть более понятным.
fileinput
как описано @ JF-Себастьяне здесь . Похоже, что вы можете работать построчно, через временный файл, с простымfor
синтаксисом.Ответы:
Сначала откройте файл и получите все свои строки из файла. Затем снова откройте файл в режиме записи и запишите свои строки обратно, за исключением строки, которую вы хотите удалить:
Вам нужно
strip("\n")
использовать символ новой строки в сравнении, потому что если ваш файл не заканчивается символом новой строки, то и последнийline
не будет.источник
Решение этой проблемы только с одним открытием:
Это решение открывает файл в режиме r / w («r +») и использует поиск, чтобы сбросить f-указатель, а затем усечь, чтобы удалить все после последней записи.
источник
for
цикле, вы получите частично перезаписанный файл с дублирующимися линиями или половиной обрезанной строки. Возможно, вы захотитеf.truncate()
сразу послеf.seek(0)
этого. Таким образом, если вы получите ошибку, вы просто получите неполный файл. Но реальное решение (если у вас есть место на диске) - вывести во временный файл, а затем использоватьos.replace()
илиpathlib.Path(temp_filename).replace(original_filename)
заменить его оригиналом после того, как все будет успешно.i.strip('\n') != "line you want to remove..."
как указано в принятом ответе, это прекрасно решило бы мою проблему. Потому что простоi
ничего не сделал для меняЛучший и самый быстрый вариант, вместо того, чтобы хранить все в списке и заново открывать файл, чтобы записать его, - по моему мнению, переписать файл в другом месте.
Это оно! В одном цикле и только один вы можете сделать то же самое. Это будет намного быстрее.
источник
(output.write(line) for line in input if line!="nickname_to_delete"+"\n")
subprocess.call(['mv', 'newfile.txt', 'yourfile.txt'])
os.replace
(новинка в python v 3.3) более кроссплатформенная, чем системный вызовmv
.Это "вилка" от @Lother (который, я считаю, следует считать правильным ответом).
Для такого файла:
Эта вилка из решения Лотера отлично работает:
Улучшения:
with open
, которые отказываются от использованияf.close()
if/else
для оценки, если строка не присутствует в текущей строкеисточник
Проблема с чтением строк на первом проходе и внесением изменений (удалением определенных строк) на втором проходе заключается в том, что если у вас большие размеры файлов, вам не хватит ОЗУ. Вместо этого, лучший подход - читать строки по одной и записывать их в отдельный файл, исключая ненужные. Я использовал этот подход для файлов размером 12-50 ГБ, и использование оперативной памяти остается практически постоянным. Только циклы процессора показывают обработку в процессе.
источник
Мне понравился подход fileinput, как объяснено в этом ответе: удаление строки из текстового файла (python)
Например, у меня есть файл с пустыми строками, и я хочу удалить пустые строки, вот как я решил это:
источник
Если вы используете Linux, вы можете попробовать следующий подход.
Предположим, у вас есть текстовый файл с именем
animal.txt
:Удалить первую строку:
затем
источник
Я думаю, что если вы прочитаете файл в список, то выполните итерацию по списку, чтобы найти псевдоним, от которого вы хотите избавиться. Вы можете сделать это очень эффективно, не создавая дополнительные файлы, но вам придется записать результат обратно в исходный файл.
Вот как я могу это сделать:
Я предполагаю,
nicknames.csv
содержит данные, такие как:Затем загрузите файл в список:
Далее, переходим к списку, чтобы соответствовать вашим входам для удаления:
Наконец, запишите результат обратно в файл:
источник
В общем, вы не можете; Вы должны написать весь файл снова (по крайней мере, с момента изменения до конца).
В некоторых конкретных случаях вы можете сделать лучше, чем это -
если все ваши элементы данных имеют одинаковую длину и не в определенном порядке, и вы знаете смещение того, от которого хотите избавиться, вы можете скопировать последний элемент поверх того, который нужно удалить, и обрезать файл до последнего элемента ;
или вы можете просто перезаписать блок данных значением «это плохие данные, пропустить его» или оставить флаг «этот элемент был удален» в ваших сохраненных элементах данных, чтобы вы могли пометить его как удаленный, не изменяя файл другим способом.
Это, вероятно, излишне для коротких документов (что-нибудь под 100 КБ?).
источник
Возможно, вы уже получили правильный ответ, но здесь мой. Вместо того, чтобы использовать список для сбора нефильтрованных данных (что
readlines()
делает метод), я использую два файла. Один предназначен для хранения основных данных, а второй - для фильтрации данных при удалении определенной строки. Вот код:Надеюсь, вы найдете это полезным! :)
источник
Сохраните строки файла в списке, затем удалите из списка строку, которую хотите удалить, и запишите оставшиеся строки в новый файл.
источник
Вот еще один способ удалить некоторые строки из файла:
источник
Мне нравится этот метод, использующий fileinput и метод inplace:
Это немного менее многословно, чем другие ответы и достаточно быстро для
источник
Предполагая, что вы можете загрузить свой полный текстовый файл. Затем вы определяете список нежелательных псевдонимов, а затем заменяете их пустой строкой "".
источник
Чтобы удалить конкретную строку файла по номеру строки :
Замените переменные filename и line_to_delete на имя вашего файла и номер строки, которую вы хотите удалить.
Пример вывода :
источник
for nb, line in enumerate(f.readlines())
Возьмите содержимое файла, разбейте его на новую строку в кортеж. Затем получите доступ к номеру строки вашего кортежа, присоедините его к кортежу результата и перезапишите файл.
источник
tuple(f.read().split('\n'))
?? (2) «получить доступ к номеру строки вашего кортежа» и «присоединиться к вашему кортежу результата» звучит довольно загадочно; Фактический код Python может быть более понятным.