Лучший способ удалить строку в файле с помощью python?

#python #file-io

#python #file-io

Вопрос:

Я хочу удалить строку в файле; в настоящее время я создаю новый файл, копируя все строки, кроме той, которую я хочу удалить, удаляя старый файл и переименовывая новый в то же имя файла, что и старый. Есть ли лучший способ удалить строку?

 f = open('./todo.txt', 'r')
newF = open('./todo-run.txt', 'a')
lines = f.readlines()
cLine = lines[int(index) - 1]

for line in lines:
  if line != cLine:
    newF.write(line)
f.close()
newF.close()
os.remove('./todo.txt')
shutil.move('./todo-run.txt', './todo.txt')
  

Комментарии:

1. Возможно, вы сможете эффективно удалить строку на месте, не перетасовывая все последующие строки. Можно ли просто заменить ее пробелом, например? или превратился в комментарий, который потребитель проигнорирует?

Ответ №1:

Решение в sed, которое вы могли бы вызвать с помощью «подпроцесса». Например, чтобы удалить строку 18, выполните:

 sed -i '18 d' filename
  

Ответ №2:

Каким образом лучше? Вы могли бы, например, перетасовать данные внутри файла, а затем обрезать его, используя меньше памяти, но больше поиска (особенно если вы адаптируете его, чтобы не читать последнюю часть за один фрагмент):

 def cutfile(file, startcut, endcut):
  file.seek(endcut)
  dataafter=file.read()
  file.seek(startcut)
  file.write(dataafter)
  file.truncate()
  

Или вы не могли удалить старый файл перед переименованием, чтобы получать атомарные обновления. Это действительно зависит от ваших целей.

Ответ №3:

Он не намного лучше вашего, но (поскольку ваш файл, похоже, помещается в основную память) вы могли бы попробовать это:

 f = open(filepath, 'r')
lines = [line.rstrip('n') for line in f if not <CONDITION>]
f.close()
f.open('filepath, 'w')
f.write('n'.join(lines))
f.close()
  

Ответ №4:

Вы могли бы перемещать строки после ненужной строки вверх, перезаписывая по одной за раз. Хотя не намного лучше того, что вы делаете сейчас. Этот код выглядит немного забавно, если файл не заканчивается новой строкой. Я тестировал это на 64-разрядной версии Win7, Python 2.7.

move_lines.py:

 f = open('todo.txt', 'r ')
line_index = 0
prev_line_head = 0
remove_line_index = 3
move_lines = False
while True:
  line_head = f.tell()
  line = f.readline()

  if line == '': #EOF
    f.seek(prev_line_head)
    f.truncate()
    break

  if move_lines:
    f.seek(prev_line_head)
    f.write(line)
    f.flush()
    line_head = f.tell()
    line = f.readline() # read past the line we already read to start this iteration
  elif line_index == remove_line_index:
    move_lines = True
  prev_line_head = line_head
  line_index  = 1
f.close()