¿El mejor método para leer archivos delimitados por líneas nuevas y descartar las líneas nuevas?


84

Estoy tratando de determinar la mejor manera de manejar la eliminación de líneas nuevas al leer archivos delimitados por líneas nuevas en Python.

Lo que se me ocurrió es el siguiente código, incluye código desechable para probar.

import os

def getfile(filename,results):
   f = open(filename)
   filecontents = f.readlines()
   for line in filecontents:
     foo = line.strip('\n')
     results.append(foo)
   return results

blahblah = []

getfile('/tmp/foo',blahblah)

for x in blahblah:
    print x

Sugerencias


¿qué pasa con el uso de split ("/ n")?
jle


Creo que sería mejor cerrar el archivo también
Paweł Prażak

Respuestas:


196
lines = open(filename).read().splitlines()

1
Esta respuesta hace lo que estaba buscando, estoy seguro de que necesitaré agregar alguna verificación de errores y demás, pero para esta necesidad específica, es genial. ¡Gracias a todos por dar respuestas!
solarce

Me gusta esto, pero ¿cómo se cierra el archivo si no guarda el identificador del archivo? ¿O se cierra automáticamente?
IJ Kennedy

6
Con CPython, el recuento de referencias para el objeto de archivo irá a cero una vez que ya no esté en uso y el archivo se cerrará automáticamente. Para implementaciones puramente GC'd como Jython e IronPython, es posible que el archivo no se cierre hasta que se ejecute GC, por lo que esta variación concisa puede no ser óptima.
Curt Hagenlocher

2
En Mac OS X 10.7.5 con 8 GB de RAM, puedo leer archivos de hasta 2047 MB ​​(mi definición: 1 MB = 1024 x 1024 bytes). 2048MB arrojarán la excepción MemoryError.
Hai Vu

1
@WKPlus Excelente pregunta: la respuesta es "depende" stackoverflow.com/a/15099341/994153 (CPython lo cerrará ya que el recuento de referencias cae a cero, pero es posible que otras implementaciones de Python no lo cierren, así que es mejor hacerlo explícito )
Colin D Bennett

23

Aquí hay un generador que hace lo que solicitó. En este caso, usar rstrip es suficiente y un poco más rápido que strip.

lines = (line.rstrip('\n') for line in open(filename))

Sin embargo, lo más probable es que también desee utilizar esto para deshacerse de los espacios en blanco finales.

lines = (line.rstrip() for line in open(filename))

¿No debería ser [] alrededor de la RHS, no ()?
andrewb

8
@andrewb Using () da una expresión generadora, que no usa tanta memoria como usar [] (una lista de comprensión)
Jonathan Hartley

9

¿Qué opinas de este enfoque?

with open(filename) as data:
    datalines = (line.rstrip('\r\n') for line in data)
    for line in datalines:
        ...do something awesome...

La expresión del generador evita cargar el archivo completo en la memoria y withasegura el cierre del archivo


Esto es esencialmente lo mismo que la respuesta de @ TimoLinna publicada años antes ...
martineau

8
for line in file('/tmp/foo'):
    print line.strip('\n')

4

Solo usa expresiones generadoras:

blahblah = (l.rstrip() for l in open(filename))
for x in blahblah:
    print x

También quiero aconsejarle que no lea el archivo completo en la memoria: recorrer los generadores es mucho más eficiente en grandes conjuntos de datos.


3

yo uso esto

def cleaned( aFile ):
    for line in aFile:
        yield line.strip()

Entonces puedo hacer cosas como esta.

lines = list( cleaned( open("file","r") ) )

O puedo extender la limpieza con funciones adicionales para, por ejemplo, dejar líneas en blanco u omitir líneas de comentarios o lo que sea.


2

Lo haría así:

f = open('test.txt')
l = [l for l in f.readlines() if l.strip()]
f.close()
print l

Si bien la respuesta de Curt Hagenlocher es técnicamente mejor, esta respuesta es un buen punto de partida si necesita agregar otro procesamiento a cada línea.
TomOnTime

No estoy seguro de si estaba destinado a filtrar líneas en blanco, pero esto es más conciso que ... if l.strip() is not '', que es lo que necesito en mi caso.
Zach Young
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.