Intente fileinputcomo lo describe @ jf-sebastian aquí . Parece que le permite trabajar línea por línea, a través de un archivo temporal, todo con una forsintaxis simple .
Kevin
Respuestas:
205
Primero, abra el archivo y obtenga todas sus líneas del archivo. Luego, vuelva a abrir el archivo en modo de escritura y escriba sus líneas, excepto la línea que desea eliminar:
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)
Necesita strip("\n")el carácter de nueva línea en la comparación porque si su archivo no termina con un carácter de nueva línea, el último linetampoco.
¿Por qué tenemos que abrirlo y cerrarlo dos veces?
Ooker
3
@Ooker: debe abrir el archivo dos veces (y cerrarlo en el medio) porque en el primer modo es "solo lectura" porque solo está leyendo en las líneas actuales del archivo. Luego lo cierra y lo vuelve a abrir en "modo de escritura", donde el archivo se puede escribir y reemplaza el contenido del archivo sin la línea que desea eliminar.
Devin
44
¿Por qué Python no nos permite hacer esto en una línea?
Ooker
55
@Ooker, cuando lea una línea, intente imaginar un cursor moviéndose a lo largo de la línea mientras se lee. Una vez que la línea ha sido leída, el cursor ya está pasado. Cuando intentas escribir en el archivo, escribes dónde está el cursor actualmente. Al volver a abrir el archivo, restablece el cursor.
Waddas
44
Utilice el con compuesto!
Sceluswe
101
Solución a este problema con solo una apertura:
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()
Esta solución abre el archivo en modo r / w ("r +") y hace uso de buscar para restablecer el puntero f y luego truncar para eliminar todo después de la última escritura.
Esto funcionó muy bien para mí, ya que también tuve que usar lockfile (fcntl). No pude encontrar ninguna manera de usar fileinput junto con fcntl.
Easyrider
1
Sería bueno ver algunos efectos secundarios de esta solución.
user1767754
3
Yo no haría esto. Si obtiene un error en el forbucle, terminará con un archivo parcialmente sobrescrito, con líneas duplicadas o una mitad cortada. Es posible que desee f.truncate()justo después f.seek(0)en su lugar. De esa forma, si obtiene un error, terminará con un archivo incompleto. Pero la solución real (si tiene espacio en el disco) es generar un archivo temporal y luego usarlo os.replace()o pathlib.Path(temp_filename).replace(original_filename)intercambiarlo con el original después de que todo haya tenido éxito.
Boris
Podría agregar i.strip('\n') != "line you want to remove..."como se menciona en la respuesta aceptada, eso resolvería perfectamente mi problema. Porque simplemente ino hizo nada por mí
Mangohero1
31
En mi opinión, la mejor y más rápida opción, en lugar de almacenar todo en una lista y volver a abrir el archivo para escribirlo, es volver a escribir el archivo en otro lugar.
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)
¡Eso es! En un bucle y solo uno puede hacer lo mismo. Será mucho más rápido
En lugar de usar el bucle normal for, podemos hacer uso de Generator Expression. De esta manera, el programa no cargará todas las líneas del archivo a la memoria, lo que no es una buena idea en el caso de archivos grandes. Solo tendrá una sola línea en la memoria a la vez. Con la expresión del generador para el bucle se verá así,(output.write(line) for line in input if line!="nickname_to_delete"+"\n")
shrishinde
44
@ShriShinde Tampoco está leyendo el archivo en la memoria al recorrer el objeto del archivo, por lo que esta solución funciona de manera idéntica a su sugerencia.
Steinar Lima
Es posible que desee eliminar el archivo original y cambiar el nombre del segundo archivo al nombre del archivo original, que con Python en un sistema operativo Linux se vería así,subprocess.call(['mv', 'newfile.txt', 'yourfile.txt'])
Max
66
os.replace(nuevo en python v 3.3) es más multiplataforma que una llamada al sistema mv.
7yl4r
Simple y genial
JuBaer AD
27
Esta es una "bifurcación" de la respuesta de @Lother (que creo que debería considerarse la respuesta correcta).
Para un archivo como este:
$ cat file.txt 1: october rust2: november rain3: december snow
Este tenedor de la solución de Lother funciona bien:
#!/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()
Mejoras:
with open, que descartan el uso de f.close()
más claro if/elsepara evaluar si la cadena no está presente en la línea actual
@yifan sí. De lo contrario, en lugar de sobrescribir el archivo, lo agregará a sí mismo (sin las líneas que está excluyendo).
Boris
5
El problema con la lectura de líneas en el primer paso y la realización de cambios (eliminación de líneas específicas) en el segundo paso es que si el tamaño de los archivos es enorme, se quedará sin RAM. En cambio, un mejor enfoque es leer líneas, una por una, y escribirlas en un archivo separado, eliminando las que no necesita. He ejecutado este enfoque con archivos tan grandes como 12-50 GB, y el uso de RAM se mantiene casi constante. Solo los ciclos de CPU muestran el procesamiento en progreso.
Esta solución no es independiente del sistema operativo, y dado que OP no especificó un sistema operativo, no hay razón para publicar una respuesta específica de Linux.
Steinar Lima
2
¡Cualquiera que sugiera el uso de subprocesos para cualquier cosa que pueda hacerse con solo Python recibe un voto negativo! Y +1 a @SteinarLima ... Estoy de acuerdo
Jamie Lindsey
2
Creo que si lees el archivo en una lista, entonces puedes iterar sobre la lista para buscar el apodo del que deseas deshacerte. Puede hacerlo de manera muy eficiente sin crear archivos adicionales, pero tendrá que volver a escribir el resultado en el archivo fuente.
Así es como podría hacer esto:
import, os, csv # and other imports you need
nicknames_to_delete =['Nick','Stephen','Mark']
A continuación, repita la lista para que coincida con las entradas que desea eliminar:
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
Por último, escriba el resultado en el archivo:
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()
En general, no puedes; tienes que volver a escribir todo el archivo (al menos desde el punto de cambio hasta el final).
En algunos casos específicos, puede hacerlo mejor que esto:
si todos sus elementos de datos tienen la misma longitud y no están en un orden específico, y conoce el desplazamiento del que desea eliminar, puede copiar el último elemento sobre el que se va a eliminar y truncar el archivo antes del último elemento ;
o simplemente podría sobrescribir el fragmento de datos con un valor de "estos son datos incorrectos, omitirlo" o mantener una marca de "este elemento ha sido eliminado" en los elementos de datos guardados de modo que pueda marcarlo como eliminado sin modificar el archivo.
Probablemente esto sea excesivo para documentos cortos (¿algo menor a 100 KB?).
Probablemente, ya obtuviste una respuesta correcta, pero aquí está la mía. En lugar de usar una lista para recopilar datos sin filtrar (qué readlines()método hace), utilizo dos archivos. Uno es para mantener los datos principales, y el segundo es para filtrar los datos cuando elimina una cadena específica. Aquí hay un código:
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()
Guarde las líneas del archivo en una lista, luego elimine de la lista la línea que desea eliminar y escriba las líneas restantes en un nuevo archivo
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)
Si su archivo no termina con una nueva línea, este código no eliminará la última línea, incluso si contiene una palabra que desea eliminar.
Boris
0
Aquí hay otro método para eliminar una / alguna línea (s) de un archivo:
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()
Suponiendo que pueda cargar su archivo txt completo. Luego define una lista de apodos no deseados y luego los sustituye con una cadena vacía "".
# 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)
no hay necesidad de construir un dict, solo usefor nb, line in enumerate(f.readlines())
Dionys
-3
Tome el contenido del archivo, divídalo por una nueva línea en una tupla. Luego, acceda al número de línea de su tupla, únase a su tupla de resultado y sobrescriba el archivo.
(1) ¿quieres decir tuple(f.read().split('\n'))? (2) "acceder al número de línea de su tupla" y "unirse a su tupla resultante" suena bastante misterioso; El código real de Python podría ser más comprensible.
fileinput
como lo describe @ jf-sebastian aquí . Parece que le permite trabajar línea por línea, a través de un archivo temporal, todo con unafor
sintaxis simple .Respuestas:
Primero, abra el archivo y obtenga todas sus líneas del archivo. Luego, vuelva a abrir el archivo en modo de escritura y escriba sus líneas, excepto la línea que desea eliminar:
Necesita
strip("\n")
el carácter de nueva línea en la comparación porque si su archivo no termina con un carácter de nueva línea, el últimoline
tampoco.fuente
Solución a este problema con solo una apertura:
Esta solución abre el archivo en modo r / w ("r +") y hace uso de buscar para restablecer el puntero f y luego truncar para eliminar todo después de la última escritura.
fuente
for
bucle, terminará con un archivo parcialmente sobrescrito, con líneas duplicadas o una mitad cortada. Es posible que deseef.truncate()
justo despuésf.seek(0)
en su lugar. De esa forma, si obtiene un error, terminará con un archivo incompleto. Pero la solución real (si tiene espacio en el disco) es generar un archivo temporal y luego usarloos.replace()
opathlib.Path(temp_filename).replace(original_filename)
intercambiarlo con el original después de que todo haya tenido éxito.i.strip('\n') != "line you want to remove..."
como se menciona en la respuesta aceptada, eso resolvería perfectamente mi problema. Porque simplementei
no hizo nada por míEn mi opinión, la mejor y más rápida opción, en lugar de almacenar todo en una lista y volver a abrir el archivo para escribirlo, es volver a escribir el archivo en otro lugar.
¡Eso es! En un bucle y solo uno puede hacer lo mismo. Será mucho más rápido
fuente
(output.write(line) for line in input if line!="nickname_to_delete"+"\n")
subprocess.call(['mv', 'newfile.txt', 'yourfile.txt'])
os.replace
(nuevo en python v 3.3) es más multiplataforma que una llamada al sistemamv
.Esta es una "bifurcación" de la respuesta de @Lother (que creo que debería considerarse la respuesta correcta).
Para un archivo como este:
Este tenedor de la solución de Lother funciona bien:
Mejoras:
with open
, que descartan el uso def.close()
if/else
para evaluar si la cadena no está presente en la línea actualfuente
El problema con la lectura de líneas en el primer paso y la realización de cambios (eliminación de líneas específicas) en el segundo paso es que si el tamaño de los archivos es enorme, se quedará sin RAM. En cambio, un mejor enfoque es leer líneas, una por una, y escribirlas en un archivo separado, eliminando las que no necesita. He ejecutado este enfoque con archivos tan grandes como 12-50 GB, y el uso de RAM se mantiene casi constante. Solo los ciclos de CPU muestran el procesamiento en progreso.
fuente
Me gustó el enfoque de entrada de archivos como se explica en esta respuesta: Eliminar una línea de un archivo de texto (python)
Digamos, por ejemplo, que tengo un archivo que tiene líneas vacías y quiero eliminar las líneas vacías, así es como lo resolví:
fuente
Si usa Linux, puede probar el siguiente enfoque.
Supongamos que tiene un archivo de texto llamado
animal.txt
:Eliminar la primera línea:
luego
fuente
Creo que si lees el archivo en una lista, entonces puedes iterar sobre la lista para buscar el apodo del que deseas deshacerte. Puede hacerlo de manera muy eficiente sin crear archivos adicionales, pero tendrá que volver a escribir el resultado en el archivo fuente.
Así es como podría hacer esto:
Supongo que
nicknames.csv
contiene datos como:Luego cargue el archivo en la lista:
A continuación, repita la lista para que coincida con las entradas que desea eliminar:
Por último, escriba el resultado en el archivo:
fuente
En general, no puedes; tienes que volver a escribir todo el archivo (al menos desde el punto de cambio hasta el final).
En algunos casos específicos, puede hacerlo mejor que esto:
si todos sus elementos de datos tienen la misma longitud y no están en un orden específico, y conoce el desplazamiento del que desea eliminar, puede copiar el último elemento sobre el que se va a eliminar y truncar el archivo antes del último elemento ;
o simplemente podría sobrescribir el fragmento de datos con un valor de "estos son datos incorrectos, omitirlo" o mantener una marca de "este elemento ha sido eliminado" en los elementos de datos guardados de modo que pueda marcarlo como eliminado sin modificar el archivo.
Probablemente esto sea excesivo para documentos cortos (¿algo menor a 100 KB?).
fuente
Probablemente, ya obtuviste una respuesta correcta, pero aquí está la mía. En lugar de usar una lista para recopilar datos sin filtrar (qué
readlines()
método hace), utilizo dos archivos. Uno es para mantener los datos principales, y el segundo es para filtrar los datos cuando elimina una cadena específica. Aquí hay un código:¡Espero que encuentres esto útil! :)
fuente
Guarde las líneas del archivo en una lista, luego elimine de la lista la línea que desea eliminar y escriba las líneas restantes en un nuevo archivo
fuente
Aquí hay otro método para eliminar una / alguna línea (s) de un archivo:
fuente
Me gusta este método usando fileinput y el método 'in situ':
Es un poco menos prolijo que las otras respuestas y es lo suficientemente rápido para
fuente
Suponiendo que pueda cargar su archivo txt completo. Luego define una lista de apodos no deseados y luego los sustituye con una cadena vacía "".
fuente
Para eliminar una línea específica de un archivo por su número de línea :
Reemplace las variables filename y line_to_delete con el nombre de su archivo y el número de línea que desea eliminar.
Salida de ejemplo :
fuente
for nb, line in enumerate(f.readlines())
Tome el contenido del archivo, divídalo por una nueva línea en una tupla. Luego, acceda al número de línea de su tupla, únase a su tupla de resultado y sobrescriba el archivo.
fuente
tuple(f.read().split('\n'))
? (2) "acceder al número de línea de su tupla" y "unirse a su tupla resultante" suena bastante misterioso; El código real de Python podría ser más comprensible.