Borrar una línea en un archivo

Estoy teniendo un problema con un progtwig de cronometrador, en el que bash identificar una línea en un archivo iterando sobre ella y luego escribiendo las líneas A MENOS que haya algo con la variable “eliminar”, por alguna razón, está pasando por el archivo y diciendo que se elimina, pero el bucle no elimina ninguna línea.

date = input(" What is today's date? month-day-year format please. (EG 01-14-2003) ") if os.path.exists(date): today = open(date, "r") print(today.read()) delete = input(" Which appointment would you like to delete? (Please type the time EG 7:00) ") #Open the file, save the read to a variable, iterate over the file, check to see if the time is what user entered, if it is not then write it to the line, close the file. fileEdit = open(date, "r+") for line in today.readline(): print(line) if delete not in line: fileEdit.write(line) print(fileEdit.read()) today.close() fileEdit.close() print ("Appointment deleted, goodbye") 

Esto está leyendo hasta el final del archivo.

 print(today.read()) 

Cuando comienzas a iterar aquí, ya estás al final.

 for line in today.readline(): 

por lo que nunca se ingresará el bucle for. Debe volver a abrir el archivo o volver al principio.

Otro problema es que estás iterando sobre la primera línea. Probablemente quiso decir

 for line in today: 

En cualquier caso, generalmente no es una buena idea escribir en el mismo archivo que está leyendo (por ejemplo, considere el desorden en el que se encontraría el archivo si la computadora se reiniciara parcialmente)

Mejor escribir un archivo temporal y reemplazar.

Si los archivos son muy pequeños, puede leer el archivo en una lista en la memoria y luego volver a escribir el archivo nuevamente.

Una mejor idea, antes de ir demasiado lejos, es utilizar una base de datos como el módulo sqlite (que está integrado en Python)

today.readline() devuelve una sola línea. El for -loop itera sobre los caracteres en esa línea. Y como @gnibbler señaló, el archivo de today está al final del archivo en el momento en que se llama a today.readline() (por lo que devuelve una cadena de caracteres).

En general, para eliminar algo en medio de un archivo, debe reemplazarlo por completo. módulo de entrada de fileinput puede ayudar a:

 import fileinput for line in fileinput.input([date], inplace=1): if delete not in line: print line, # stdout is redirected to the `date` file 

Aquí hay casi lo mismo pero sin entrada de fileinput :

 import os from tempfile import NamedTemporaryFile filename = date dirpath = os.path.dirname(filename) with open(filename) as file, NamedTemporaryFile("w", dir=dirpath) as outfile: for line in file: if delete not in line: print >>outfile, line, # copy old content outfile.delete = False # don't delete outfile os.remove(filename) # rename() doesn't overwrite on Windows os.rename(outfile.name, filename) # or just `os.replace` in Python 3.3+ 

El problema viene de leer y escribir el mismo archivo. Aquí hay una explicación sobre eso.

Buena referencia ( Principiante Python: leer y escribir en el mismo archivo )

Entonces, cuando se encuentra en el modo r+ , tanto la lectura como la escritura en el archivo mueven el puntero del archivo hacia adelante.

Así que echemos un vistazo a tu ejemplo. Primero haces un readline. Esto mueve el puntero del archivo a la siguiente línea. Verifica si la línea que acabas de leer es válida o no y la escribes si lo es.

El problema es que acabas de sobrescribir la siguiente línea, ¡no la anterior! Así que tu código realmente está arruinando tus datos.

Básicamente, es muy difícil (e ineficiente si el archivo es grande) querer hacerlo bien. No puede eliminar bytes arbitrariamente de la mitad de un archivo. Para cada línea que desea eliminar, tendría que escribir el rest de los datos sobre ella y luego truncar el archivo al final para eliminar el espacio liberado.

Debe seguir el consejo de las otras respuestas y enviarlas a otro archivo o salida estándar.

Pues también puedes hacer lo siguiente:

 with open("input.txt",'r') as infile, open("output.txt",'w') as outfile: # code here outfile.write(line) 

En tu bucle de archivos, puedes hacer algo como:

 if delete: continue 

para omitir la línea que no desea escribir en el archivo de salida.