¿Cómo leer un archivo línea por línea en una lista?

2027

¿Cómo leo cada línea de un archivo en Python y almaceno cada línea como un elemento en una lista?

Quiero leer el archivo línea por línea y agregar cada línea al final de la lista.

Julie Raswick
fuente

Respuestas:

2174
with open(filename) as f:
    content = f.readlines()
# you may also want to remove whitespace characters like `\n` at the end of each line
content = [x.strip() for x in content] 
SilentGhost
fuente
206
No utilice file.readlines()en un forbucle, un objeto de archivo en sí es suficiente:lines = [line.rstrip('\n') for line in file]
jfs
88
En el caso de que esté trabajando con Big Data, el uso readlines()no es muy eficiente, ya que puede provocar MemoryError . En este caso, es mejor iterar sobre el archivo usando for line in f:y trabajando con cada linevariable.
DarkCygnus
77
Verifiqué el perfil de memoria de las diferentes formas dadas en las respuestas usando el procedimiento mencionado aquí . El uso de la memoria es mucho mejor cuando cada línea se lee del archivo y se procesa, como lo sugiere @DevShark aquí . Mantener todas las líneas en un objeto de colección no es una buena idea si la memoria es una restricción o si el archivo es grande. El tiempo de ejecución es similar en ambos enfoques.
Tirtha R
66
Además, .rstrip()funcionará un poco más rápido si elimina espacios en blanco de los extremos de las líneas.
Gringo Suave
Oneliner:with open(filename) as f: content = [i.strip() for i in f.readlines()]
Vishal Gupta
1002

Ver Entrada y Salida :

with open('filename') as f:
    lines = f.readlines()

o con la eliminación del carácter de nueva línea:

with open('filename') as f:
    lines = [line.rstrip() for line in f]
Felix Kling
fuente
12
Mejor, use f.read().splitlines(), lo que elimina las nuevas líneas
Mark
¿Es la segunda versión, con for line in open(filename)caja fuerte? Es decir, ¿se cerrará automáticamente el archivo?
Becko
2
Es mejor leer el archivo línea por línea en lugar de leer todo el archivo en la memoria de una vez. Hacerlo no escala bien con archivos de entrada grandes. Vea a continuación la respuesta de Robert.
Brad Hein
1
lines = [x.rstrip('\n') for x in open('data\hsf.txt','r')]Si escribo de esta manera, ¿cómo puedo cerrar el archivo después de leerlo?
Ramisa Anjum Aditi
2
Sí, hasta el punto que otros están haciendo aquí, aunque no es una "mejor práctica" usar opensin el administrador de contexto (u otra forma garantizada de cerrarlo), este no es realmente uno de esos casos, cuando el objeto no tiene más referencias para ello, se recolectará basura y se cerrará el archivo, lo que debería suceder inmediatamente por error o no, cuando la comprensión de la lista se haya procesado.
Aaron Hall
579

Esto es más explícito de lo necesario, pero hace lo que quiere.

with open("file.txt") as file_in:
    lines = []
    for line in file_in:
        lines.append(line)
robert
fuente
18
Prefiero esta respuesta, ya que no requiere cargar todo el archivo en la memoria (en este caso todavía se adjunta array, pero puede haber otras circunstancias). Ciertamente, para archivos grandes, este enfoque podría mitigar los problemas.
JohannesB
1
Agregar a una matriz es lento. No puedo pensar en un caso de uso donde esta sea la mejor solución.
Elias Strehle
@haccks, ¿es mejor porque no carga todo el archivo en la memoria o hay más?
OrigamiEye
44
Nota: Esta solución no elimina las nuevas líneas.
AMC
1
Esta solución carga todo el archivo en la memoria. No sé por qué la gente piensa que no.
andrebrait
274

Esto producirá una "matriz" de líneas del archivo.

lines = tuple(open(filename, 'r'))

opendevuelve un archivo que se puede repetir. Cuando iteras sobre un archivo, obtienes las líneas de ese archivo. tuplepuede tomar un iterador e instanciar una instancia de tupla para usted desde el iterador que le da. lineses una tupla creada a partir de las líneas del archivo.

Noctis Skytower
fuente
31
@MarshallFarrier Intenta en su lines = open(filename).read().split('\n')lugar.
Noctis Skytower
16
¿cierra el archivo?
Vanuan
55
@Vanuan Dado que no queda ninguna referencia al archivo después de ejecutar la línea, el destructor debería cerrar el archivo automáticamente.
Noctis Skytower
30
@NoctisSkytower Encuentro lines = open(filename).read().splitlines()un poco más limpio, y creo que también maneja mejor las terminaciones de línea de DOS.
jaynp
8
@ mklement0 Suponiendo un archivo de 1000 líneas, a listocupa aproximadamente un 13,22% más de espacio que a tuple. Los resultados provienen de from sys import getsizeof as g; i = [None] * 1000; round((g(list(i)) / g(tuple(i)) - 1) * 100, 2). Crear una tupletoma alrededor de 4.17% más tiempo que crear una list(con una desviación estándar de 0.16%). Los resultados provienen de correr from timeit import timeit as t; round((t('tuple(i)', 'i = [None] * 1000') / t('list(i)', 'i = [None] * 1000') - 1) * 100, 2)30 veces. Mi solución favorece el espacio sobre la velocidad cuando se desconoce la necesidad de mutabilidad.
Noctis Skytower
194

Si quieres lo \nincluido:

with open(fname) as f:
    content = f.readlines()

Si no quieres \nincluir:

with open(fname) as f:
    content = f.read().splitlines()
Eneko Alonso
fuente
168

De acuerdo con los Métodos de objetos de archivo de Python , la forma más sencilla de convertir un archivo de texto en un listes:

with open('file.txt') as f:
    my_list = list(f)

Si solo necesita iterar sobre las líneas del archivo de texto, puede usar:

with open('file.txt') as f:
    for line in f:
       ...

Vieja respuesta:

Usando withy readlines():

with open('file.txt') as f:
    lines = f.readlines()

Si no le importa cerrar el archivo, esta línea única funciona:

lines = open('file.txt').readlines()

La forma tradicional :

f = open('file.txt') # Open file on read mode
lines = f.read().split("\n") # Create a list containing all lines
f.close() # Close file
CONvid19
fuente
150

Simplemente puede hacer lo siguiente, como se ha sugerido:

with open('/your/path/file') as f:
    my_lines = f.readlines()

Tenga en cuenta que este enfoque tiene 2 desventajas:

1) Almacena todas las líneas en la memoria. En el caso general, esta es una muy mala idea. El archivo podría ser muy grande y podría quedarse sin memoria. Incluso si no es grande, es simplemente una pérdida de memoria.

2) Esto no permite el procesamiento de cada línea a medida que las lee. Entonces, si procesa sus líneas después de esto, no es eficiente (requiere dos pases en lugar de uno).

Un mejor enfoque para el caso general sería el siguiente:

with open('/your/path/file') as f:
    for line in f:
        process(line)

Donde defina su función de proceso de la forma que desee. Por ejemplo:

def process(line):
    if 'save the world' in line.lower():
         superman.save_the_world()

(La implementación de la Supermanclase se deja como un ejercicio para usted).

Esto funcionará bien para cualquier tamaño de archivo y revisará su archivo en solo 1 pasada. Por lo general, así es como funcionarán los analizadores genéricos.

DevShark
fuente
55
Esto era exactamente lo que necesitaba, y gracias por explicar las desventajas. Como principiante en Python, es increíble entender por qué una solución es la solución. ¡Salud!
Ephexx
55
Piensa un poco más Corey. ¿Realmente quieres que tu computadora lea cada línea, sin hacer nada con estas líneas? Seguramente puede darse cuenta de que siempre necesita procesarlos de una forma u otra.
DevShark
55
Siempre necesitas hacer algo con las líneas. Puede ser tan simple como imprimir las líneas o contarlas. No tiene ningún valor hacer que su proceso lea las líneas en la memoria, pero no hacer nada con él.
DevShark
2
Siempre necesitas hacer algo con ellos. Creo que el punto que está tratando de hacer es que es posible que desee aplicar una función a todos a la vez, en lugar de uno por uno. Ese es de hecho el caso a veces. Pero es muy ineficiente desde el punto de vista de la memoria hacerlo, y le impide leer archivos si su huella es mayor que su Ram. Es por eso que los analizadores genéricos suelen funcionar de la manera que describí.
DevShark
2
@PierreOcinom eso es correcto. Dado que el archivo se abre en modo de solo lectura, no puede modificar el archivo original con el código anterior. Para abrir un archivo para leer y escribir, useopen('file_path', 'r+')
DevShark
66

Datos en la lista

Supongamos que tenemos un archivo de texto con nuestros datos como en las siguientes líneas,

Contenido del archivo de texto:

line 1
line 2
line 3
  • Abra el cmd en el mismo directorio (haga clic con el botón derecho del mouse y elija cmd o PowerShell)
  • Ejecute pythony en el intérprete escriba:

El script de Python:

>>> with open("myfile.txt", encoding="utf-8") as file:
...     x = [l.rstrip("\n") for l in file]
>>> x
['line 1','line 2','line 3']

Usando append:

x = []
with open("myfile.txt") as file:
    for l in file:
        x.append(l.strip())

O:

>>> x = open("myfile.txt").read().splitlines()
>>> x
['line 1', 'line 2', 'line 3']

O:

>>> x = open("myfile.txt").readlines()
>>> x
['linea 1\n', 'line 2\n', 'line 3\n']

O:

def print_output(lines_in_textfile):
    print("lines_in_textfile =", lines_in_textfile)

y = [x.rstrip() for x in open("001.txt")]
print_output(y)

with open('001.txt', 'r', encoding='utf-8') as file:
    file = file.read().splitlines()
    print_output(file)

with open('001.txt', 'r', encoding='utf-8') as file:
    file = [x.rstrip("\n") for x in file]
    print_output(file)

salida:

lines_in_textfile = ['line 1', 'line 2', 'line 3']
lines_in_textfile = ['line 1', 'line 2', 'line 3']
lines_in_textfile = ['line 1', 'line 2', 'line 3']
Giovanni G. PY
fuente
1
read().splitlines()es proporcionado por Python: es simple readlines()(que probablemente sea más rápido, ya que es menos derrochador).
Eric O Lebigot
1
@EricOLebigot de los ejemplos que se muestran, se ve read().splitlines()y readlines()no produce el mismo resultado. ¿Estás seguro de que son equivalentes?
craq
1
Si usa solo líneas de lectura, debe usar el método de tira para deshacerse de la \ n en el texto, así que cambié los últimos ejemplos usando una comprensión de lista para tener el mismo resultado en ambos casos. Por lo tanto, si usa read (). Readlines () tendrá un elemento "limpio" con la línea y sin el carácter de nueva línea, de lo contrario, debe hacer lo que ve en el código anterior.
Giovanni G. PY
1
En efecto. Tenga en cuenta que en el código anterior se strip()deben rstrip("\n")eliminar todos los espacios o alrededor de una línea. Además, no tiene sentido hacer readlines()una comprensión de la lista: simplemente iterar sobre el archivo es mejor, ya que no pierde tiempo y memoria al crear una lista intermedia de las líneas.
Eric O Lebigot
1
@EricOLebigot Hecho, gracias.
Giovanni G. PY
43

Para leer un archivo en una lista, debe hacer tres cosas:

  • Abre el archivo
  • Lee el archivo
  • Almacenar los contenidos como lista

Afortunadamente, Python hace que sea muy fácil hacer estas cosas, por lo que la forma más corta de leer un archivo en una lista es:

lst = list(open(filename))

Sin embargo, agregaré más explicaciones.

Abriendo el archivo

Supongo que desea abrir un archivo específico y no trata directamente con un identificador de archivo (o un identificador de archivo). La función más utilizada para abrir un archivo en Python es openque requiere un argumento obligatorio y dos opcionales en Python 2.7:

  • Nombre del archivo
  • Modo
  • Almacenamiento en búfer (ignoraré este argumento en esta respuesta)

El nombre del archivo debe ser una cadena que represente la ruta al archivo . Por ejemplo:

open('afile')   # opens the file named afile in the current working directory
open('adir/afile')            # relative path (relative to the current working directory)
open('C:/users/aname/afile')  # absolute path (windows)
open('/usr/local/afile')      # absolute path (linux)

Tenga en cuenta que la extensión del archivo debe especificarse. Esto es especialmente importante para los usuarios de Windows porque las extensiones de archivo como .txto .doc, etc. están ocultas de forma predeterminada cuando se ven en el explorador.

El segundo argumento es el mode, esr por defecto, significa "solo lectura". Eso es exactamente lo que necesitas en tu caso.

Pero en caso de que realmente quiera crear un archivo y / o escribir en un archivo, necesitará un argumento diferente aquí. Hay una excelente respuesta si desea una visión general .

Para leer un archivo, puede omitirlo modeo pasarlo explícitamente:

open(filename)
open(filename, 'r')

Ambos abrirán el archivo en modo de solo lectura. En caso de que quiera leer un archivo binario en Windows, debe usar el modo rb:

open(filename, 'rb')

En otras plataformas, el 'b'(modo binario) simplemente se ignora.


Ahora que le he mostrado cómo hacer openel archivo, hablemos del hecho de que siempre necesitaclose nuevo. De lo contrario, mantendrá un identificador de archivo abierto en el archivo hasta que finalice el proceso (o Python arroje el identificador de archivo).

Si bien podrías usar:

f = open(filename)
# ... do stuff with f
f.close()

Eso no podrá cerrar el archivo cuando algo entre openy closelanza una excepción. Puede evitar eso usando un tryy finally:

f = open(filename)
# nothing in between!
try:
    # do stuff with f
finally:
    f.close()

Sin embargo Python proporciona gestores de contexto que tienen una sintaxis más bonita (pero para los openque es casi idéntico al tryy finallyarriba):

with open(filename) as f:
    # do stuff with f
# The file is always closed after the with-scope ends.

¡El último enfoque es el enfoque recomendado para abrir un archivo en Python!

Leyendo el archivo

Bien, has abierto el archivo, ¿ahora cómo leerlo?

La openfunción devuelve un fileobjeto y admite el protocolo de iteración Pythons. Cada iteración te dará una línea:

with open(filename) as f:
    for line in f:
        print(line)

Esto imprimirá cada línea del archivo. Sin embargo, tenga en cuenta que cada línea contendrá un carácter de nueva línea \nal final (es posible que desee verificar si su Python está construido con soporte universal de nuevas líneas ; de lo contrario, también podría tener \r\nWindows o \rMac como nuevas líneas). Si no quiere eso, puede simplemente eliminar el último carácter (o los dos últimos caracteres en Windows):

with open(filename) as f:
    for line in f:
        print(line[:-1])

Pero la última línea no necesariamente tiene una nueva línea final, por lo que no se debe usar eso. Se podría verificar si termina con una nueva línea final y, de ser así, eliminarla:

with open(filename) as f:
    for line in f:
        if line.endswith('\n'):
            line = line[:-1]
        print(line)

Pero simplemente puede eliminar todos los espacios en blanco (incluido el \ncarácter) del final de la cadena , esto también eliminará todos los demás espacios en blanco finales, por lo que debe tener cuidado si estos son importantes:

with open(filename) as f:
    for line in f:
        print(f.rstrip())

Sin embargo, si las líneas terminan con \r\n("nuevas líneas " de Windows) eso .rstrip()también se encargará de \r!

Almacenar los contenidos como lista

Ahora que sabe cómo abrir el archivo y leerlo, es hora de almacenar el contenido en una lista. La opción más simple sería usar la listfunción:

with open(filename) as f:
    lst = list(f)

En caso de que desee eliminar las nuevas líneas finales, puede utilizar una lista de comprensión en su lugar:

with open(filename) as f:
    lst = [line.rstrip() for line in f]

O incluso más simple: el .readlines()método del fileobjeto por defecto devuelve una listde las líneas:

with open(filename) as f:
    lst = f.readlines()

Esto también incluirá los caracteres de la nueva línea final, si no los desea, recomendaría el [line.rstrip() for line in f]enfoque porque evita mantener dos listas que contienen todas las líneas en la memoria.

Hay una opción adicional para obtener el resultado deseado, sin embargo, es bastante "subóptimo": readel archivo completo en una cadena y luego dividido en nuevas líneas:

with open(filename) as f:
    lst = f.read().split('\n')

o:

with open(filename) as f:
    lst = f.read().splitlines()

Estos se ocupan de las nuevas líneas finales automáticamente porque el splitpersonaje no está incluido. Sin embargo, no son ideales porque mantiene el archivo como cadena y como una lista de líneas en la memoria.

Resumen

  • Úselo with open(...) as fal abrir archivos porque no necesita ocuparse de cerrar el archivo usted mismo y cierra el archivo incluso si ocurre alguna excepción.
  • filelos objetos admiten el protocolo de iteración, por lo que leer un archivo línea por línea es tan simple como for line in the_file_object:.
  • Siempre busque en la documentación las funciones / clases disponibles. La mayoría de las veces hay una combinación perfecta para la tarea o al menos una o dos buenas. La elección obvia en este caso sería, readlines()pero si desea procesar las líneas antes de almacenarlas en la lista, recomendaría una simple comprensión de la lista.
MSeifert
fuente
¡El último enfoque es el enfoque recomendado para abrir un archivo en Python! ¿Por qué es el último, entonces? ¿Acaso la gran mayoría de las personas solo mira las primeras líneas de una respuesta antes de continuar?
AMC
@AMC No he pensado mucho cuando escribí la respuesta. ¿Crees que debería ponerlo en la parte superior de la respuesta?
MSeifert
Podría ser lo mejor, sí. También me di cuenta de que mencionas Python 2, por lo que también podría actualizarse.
AMC
Ah, la pregunta fue originalmente etiquetada como python-2.x. Puede tener sentido actualizarlo de manera más general. Veré si llego a eso la próxima vez. Gracias por sus sugerencias ¡Muy apreciado!
MSeifert
42

Forma limpia y pitónica de leer las líneas de un archivo en una lista


En primer lugar, debe centrarse en abrir su archivo y leer su contenido de manera eficiente y pitónica. Aquí hay un ejemplo de la forma en que personalmente NO prefiero:

infile = open('my_file.txt', 'r')  # Open the file for reading.

data = infile.read()  # Read the contents of the file.

infile.close()  # Close the file since we're done using it.

En cambio, prefiero el siguiente método de abrir archivos para leer y escribir, ya que es muy limpio y no requiere un paso adicional para cerrar el archivo una vez que haya terminado de usarlo. En la siguiente declaración, abrimos el archivo para leerlo y lo asignamos a la variable 'archivo'. Una vez que el código dentro de esta declaración haya terminado de ejecutarse, el archivo se cerrará automáticamente.

# Open the file for reading.
with open('my_file.txt', 'r') as infile:

    data = infile.read()  # Read the contents of the file into memory.

Ahora debemos centrarnos en incorporar estos datos a una lista de Python porque son iterables, eficientes y flexibles. En su caso, el objetivo deseado es poner cada línea del archivo de texto en un elemento separado. Para lograr esto, utilizaremos el método splitlines () de la siguiente manera:

# Return a list of the lines, breaking at line boundaries.
my_list = data.splitlines()

El producto final:

# Open the file for reading.
with open('my_file.txt', 'r') as infile:

    data = infile.read()  # Read the contents of the file into memory.

# Return a list of the lines, breaking at line boundaries.
my_list = data.splitlines()

Prueba de nuestro código:

  • Contenido del archivo de texto:
     A fost odatã ca-n povesti,
     A fost ca niciodatã,
     Din rude mãri împãrãtesti,
     O prea frumoasã fatã.
  • Imprima declaraciones para fines de prueba:
    print my_list  # Print the list.

    # Print each line in the list.
    for line in my_list:
        print line

    # Print the fourth element in this list.
    print my_list[3]
  • Salida (de aspecto diferente debido a los caracteres unicode):
     ['A fost odat\xc3\xa3 ca-n povesti,', 'A fost ca niciodat\xc3\xa3,',
     'Din rude m\xc3\xa3ri \xc3\xaemp\xc3\xa3r\xc3\xa3testi,', 'O prea
     frumoas\xc3\xa3 fat\xc3\xa3.']

     A fost odatã ca-n povesti, A fost ca niciodatã, Din rude mãri
     împãrãtesti, O prea frumoasã fatã.

     O prea frumoasã fatã.
Johnny
fuente
30

Introducido en Python 3.4, pathlibtiene un método realmente conveniente para leer texto de archivos, como sigue:

from pathlib import Path
p = Path('my_text_file')
lines = p.read_text().splitlines()

(La splitlinesllamada es lo que lo convierte de una cadena que contiene todo el contenido del archivo a una lista de líneas en el archivo).

pathlibtiene muchas comodidades prácticas. read_textes agradable y conciso, y no tiene que preocuparse por abrir y cerrar el archivo. Si todo lo que necesita hacer con el archivo es leerlo todo de una vez, es una buena opción.

LangeHaare
fuente
29

Aquí hay una opción más mediante el uso de listas de comprensión en los archivos;

lines = [line.rstrip() for line in open('file.txt')]

Esta debería ser una forma más eficiente ya que la mayor parte del trabajo se realiza dentro del intérprete de Python.

usuario1833244
fuente
10
rstrip()potencialmente elimina todo el espacio en blanco al final, no solo el \n; uso .rstrip('\n').
mklement0
Esto tampoco garantiza que el archivo se cierre después de leerlo en todas las implementaciones de Python (aunque en CPython, la implementación principal de Python, lo será).
Mark Amery
1
Esta debería ser una forma más eficiente ya que la mayor parte del trabajo se realiza dentro del intérprete de Python. Qué significa eso?
AMC
28
f = open("your_file.txt",'r')
out = f.readlines() # will append in the list out

Ahora variable out es una lista (matriz) de lo que desea. Puedes hacer lo siguiente:

for line in out:
    print (line)

O:

for line in f:
    print (line)

Obtendrás los mismos resultados.

moldavo
fuente
27

Leer y escribir archivos de texto con Python 2 y Python 3; funciona con Unicode

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# Define data
lines = ['     A first string  ',
         'A Unicode sample: €',
         'German: äöüß']

# Write text file
with open('file.txt', 'w') as fp:
    fp.write('\n'.join(lines))

# Read text file
with open('file.txt', 'r') as fp:
    read_lines = fp.readlines()
    read_lines = [line.rstrip('\n') for line in read_lines]

print(lines == read_lines)

Cosas a tener en cuenta:

  • withes un llamado administrador de contexto . Se asegura de que el archivo abierto se vuelva a cerrar.
  • Todas las soluciones aquí que simplemente hacen .strip()o .rstrip()no reproducirán, linesya que también eliminan el espacio en blanco.

Finales de archivo comunes

.txt

Escritura / lectura de archivos más avanzada

Para su aplicación, lo siguiente puede ser importante:

  • Soporte por otros lenguajes de programación.
  • Rendimiento de lectura / escritura
  • Compacidad (tamaño del archivo)

Ver también: Comparación de formatos de serialización de datos.

En caso de que esté buscando una manera de crear archivos de configuración, puede leer mi breve artículo Archivos de configuración en Python .

Martin Thoma
fuente
26

Otra opción es numpy.genfromtxt, por ejemplo:

import numpy as np
data = np.genfromtxt("yourfile.dat",delimiter="\n")

Esto creará datauna matriz NumPy con tantas filas como haya en su archivo.

atomh33ls
fuente
25

Si desea leer un archivo desde la línea de comandos o desde stdin, también puede usar el fileinputmódulo:

# reader.py
import fileinput

content = []
for line in fileinput.input():
    content.append(line.strip())

fileinput.close()

Pásale archivos así:

$ python reader.py textfile.txt 

Lea más aquí: http://docs.python.org/2/library/fileinput.html

oliland
fuente
20

La forma más sencilla de hacerlo

Una forma simple es:

  1. Lea todo el archivo como una cadena
  2. Dividir la cuerda línea por línea

En una línea, eso daría:

lines = open('C:/path/file.txt').read().splitlines()

Sin embargo, esta es una forma bastante ineficiente ya que almacenará 2 versiones del contenido en la memoria (probablemente no sea un gran problema para archivos pequeños, pero aún así). [Gracias Mark Amery].

Hay 2 formas más fáciles:

  1. Usar el archivo como iterador
lines = list(open('C:/path/file.txt'))
# ... or if you want to have a list without EOL characters
lines = [l.rstrip() for l in open('C:/path/file.txt')]
  1. Si está utilizando Python 3.4 o superior, mejor use pathlibpara crear una ruta para su archivo que pueda usar para otras operaciones en su programa:
from pathlib import Path
file_path = Path("C:/path/file.txt") 
lines = file_path.read_text().split_lines()
# ... or ... 
lines = [l.rstrip() for l in file_path.open()]
Jean-Francois T.
fuente
Este es un mal enfoque. Por un lado, llamar .read().splitlines()no es de ninguna manera "más simple" que simplemente llamar .readlines(). Por otro lado, es ineficiente de memoria; está almacenando innecesariamente dos versiones del contenido del archivo (la única cadena devuelta por .read(), y la lista de cadenas devueltas por splitlines()) en la memoria a la vez.
Mark Amery
@MarkAmery True. Gracias por resaltar esto. He actualizado mi respuesta.
Jean-Francois T.
14

Solo use las funciones splitlines (). Aquí hay un ejemplo.

inp = "file.txt"
data = open(inp)
dat = data.read()
lst = dat.splitlines()
print lst
# print(lst) # for python 3

En la salida tendrás la lista de líneas.

Abdullah Bilal
fuente
Memoria ineficiente en comparación con el uso .readlines(). Esto coloca dos copias del contenido del archivo en la memoria a la vez (una como una cadena enorme y otra como una lista de líneas).
Mark Amery
11

Si desea enfrentarse a un archivo muy grande / enorme y quiere leer más rápido (imagine que está en una competencia de codificación Topcoder / Hackerrank), puede leer una porción de líneas considerablemente más grande en un búfer de memoria a la vez, en lugar de solo itere línea por línea a nivel de archivo.

buffersize = 2**16
with open(path) as f: 
    while True:
        lines_buffer = f.readlines(buffersize)
        if not lines_buffer:
            break
        for line in lines_buffer:
            process(line)
pambda
fuente
¿Qué hace el proceso (línea)? Me sale un error que no hay tal variable definida. Supongo que algo necesita ser importado e intenté importar multiprocesamiento. Proceso, pero eso no es todo, supongo. ¿Podrías por favor elaborar? Gracias
Newskooler
1
process(line)es una función que necesita implementar para procesar los datos. por ejemplo, en lugar de esa línea, si la usa print(line), imprimirá cada línea desde el buffer de líneas.
Khanal
f.readlines (tamaño de búfer) devuelve un búfer inmutable. si desea leer directamente en su búfer, debe usar la función readinto (). Seré mucho más rápido
David Dehghan
7

Las formas más fáciles de hacerlo con algunos beneficios adicionales son:

lines = list(open('filename'))

o

lines = tuple(open('filename'))

o

lines = set(open('filename'))

En el caso de set, debemos recordar que no tenemos el orden de línea preservado y deshacernos de las líneas duplicadas.

A continuación, agregué un suplemento importante de @MarkAmery :

Dado que no está llamando .closeal objeto de archivo ni está utilizando una withdeclaración, en algunas implementaciones de Python , el archivo puede no cerrarse después de la lectura y su proceso perderá un identificador de archivo abierto .

En CPython (la implementación normal de Python que usa la mayoría de las personas), esto no es un problema ya que el objeto del archivo se recolectará inmediatamente y esto cerrará el archivo, pero no obstante, generalmente se considera la mejor práctica para hacer algo como :

with open('filename') as f: lines = list(f) 

para asegurar que el archivo se cierre independientemente de lo que implementación de Python que esté utilizando.

simhumileco
fuente
1
Dado que no está llamando .closeal objeto de archivo ni está utilizando una withdeclaración, en algunas implementaciones de Python el archivo puede no cerrarse después de la lectura y su proceso perderá un identificador de archivo abierto. En CPython (la implementación normal de Python que usa la mayoría de las personas), esto no es un problema ya que el objeto del archivo se recolectará inmediatamente y esto cerrará el archivo, pero generalmente se considera la mejor práctica para hacer algo como with open('filename') as f: lines = list(f)asegurarse de que el archivo se cierra independientemente de la implementación de Python que esté utilizando.
Mark Amery
Gracias por tu gran comentario @MarkAmery! Realmente lo aprecio.
simhumileco
1
@simhumileco ¿Por qué dura la mejor solución (correcta)?
AMC
@AMC porque primero, quería mostrar las formas más simples y por coherencia de razonamiento.
simhumileco
Además, espero que mi respuesta sea hecha para que sea breve y fácil de leer.
simhumileco
4

Utilizar este:

import pandas as pd
data = pd.read_csv(filename) # You can also add parameters such as header, sep, etc.
array = data.values

dataes un tipo de marco de datos y utiliza valores para obtener ndarray. También puede obtener una lista usando array.tolist().

Cero
fuente
pandas.read_csv()es para leer datos CSV , ¿cómo es apropiado aquí?
AMC
4

Esquema y resumen

Con a filename, manejando el archivo desde un Path(filename)objeto, o directamente con open(filename) as f, realice una de las siguientes acciones:

  • list(fileinput.input(filename))
  • utilizando with path.open() as f, llamef.readlines()
  • list(f)
  • path.read_text().splitlines()
  • path.read_text().splitlines(keepends=True)
  • iterar sobre fileinput.inputo fylist.append cada una línea a la vez
  • pasar fa un límitelist.extend método
  • utilizar fen una lista de comprensión

Explico el caso de uso para cada uno a continuación.

En Python, ¿cómo leo un archivo línea por línea?

Esta es una excelente pregunta. Primero, creemos algunos datos de muestra:

from pathlib import Path
Path('filename').write_text('foo\nbar\nbaz')

Los objetos de archivo son iteradores perezosos, así que simplemente repítelo.

filename = 'filename'
with open(filename) as f:
    for line in f:
        line # do something with the line

Alternativamente, si tiene varios archivos, use fileinput.inputotro iterador perezoso. Con solo un archivo:

import fileinput

for line in fileinput.input(filename): 
    line # process the line

o para varios archivos, pásele una lista de nombres de archivo:

for line in fileinput.input([filename]*2): 
    line # process the line

Una vez más, fy fileinput.inputarriba, ambos son / return iteradores perezosos. Solo puede usar un iterador una vez, por lo que para proporcionar un código funcional y evitar la verbosidad, usaré un poco más conciso fileinput.input(filename)donde sea apropiado a partir de aquí.

En Python, ¿cómo leo un archivo línea por línea en una lista?

Ah, pero lo quieres en una lista por alguna razón? Lo evitaría si fuera posible. Pero si insiste ... simplemente pase el resultado de fileinput.input(filename)a list:

list(fileinput.input(filename))

Otra respuesta directa es llamar f.readlines, que devuelve el contenido del archivo (hasta un hintnúmero opcional de caracteres, para que pueda dividirlo en varias listas de esa manera).

Puede acceder a este objeto de archivo de dos maneras. Una forma es pasar el nombre del archivo al archivo openincorporado:

filename = 'filename'

with open(filename) as f:
    f.readlines()

o usando el nuevo objeto Path del pathlibmódulo (que me ha gustado bastante y usaré a partir de ahora):

from pathlib import Path

path = Path(filename)

with path.open() as f:
    f.readlines()

list también consumirá el iterador de archivo y devolverá una lista, un método bastante directo también:

with path.open() as f:
    list(f)

Si no le importa leer todo el texto en la memoria como una sola cadena antes de dividirlo, puede hacerlo como una línea con el Pathobjeto y el splitlines()método de cadena. Por defecto, splitlineselimina las nuevas líneas:

path.read_text().splitlines()

Si desea conservar las nuevas líneas, pase keepends=True:

path.read_text().splitlines(keepends=True)

Quiero leer el archivo línea por línea y agregar cada línea al final de la lista.

Ahora es un poco tonto pedirlo, dado que hemos demostrado el resultado final fácilmente con varios métodos. Pero es posible que necesite filtrar u operar en las líneas a medida que hace su lista, así que hagamos caso a esta solicitud.

El uso list.appendle permitiría filtrar u operar en cada línea antes de agregarla:

line_list = []
for line in fileinput.input(filename):
    line_list.append(line)

line_list

El uso list.extendsería un poco más directo y quizás útil si tiene una lista preexistente:

line_list = []
line_list.extend(fileinput.input(filename))
line_list

O, más idiomáticamente, podríamos usar una lista de comprensión, y mapear y filtrar dentro de ella si es deseable:

[line for line in fileinput.input(filename)]

O incluso más directamente, para cerrar el círculo, simplemente páselo a la lista para crear una nueva lista directamente sin operar en las líneas:

list(fileinput.input(filename))

Conclusión

Ha visto muchas formas de obtener líneas de un archivo en una lista, pero le recomiendo que evite materializar grandes cantidades de datos en una lista y, en su lugar, use la iteración perezosa de Python para procesar los datos si es posible.

Es decir, prefiero fileinput.inputo with path.open() as f.

Aaron Hall
fuente
4

En caso de que también haya líneas vacías en el documento, me gusta leer el contenido y pasarlo filterpara evitar elementos de cadena vacíos.

with open(myFile, "r") as f:
    excludeFileContent = list(filter(None, f.read().splitlines()))
jeanggi90
fuente
1
Esto no es pitónico, ten cuidado.
AMC
3

También puede usar el comando loadtxt en NumPy. Esto busca menos condiciones que genfromtxt, por lo que puede ser más rápido.

import numpy
data = numpy.loadtxt(filename, delimiter="\n")
asampat3090
fuente
2

Me gusta usar lo siguiente. Leyendo las líneas de inmediato.

contents = []
for line in open(filepath, 'r').readlines():
    contents.append(line.strip())

O usando la comprensión de la lista:

contents = [line.strip() for line in open(filepath, 'r').readlines()]
Daniel
fuente
2
No es necesario readlines(), lo que incluso incurre en una penalización de memoria. Simplemente puede eliminarlo, ya que iterar sobre un archivo (texto) le da a cada línea a su vez.
Eric O Lebigot
2
Debe usar una withdeclaración para abrir (e cerrar implícitamente) el archivo.
Aran-Fey
2

Probaría uno de los métodos mencionados a continuación. El archivo de ejemplo que uso tiene el nombre dummy.txt. Puedes encontrar el archivo aquí . Supongo que el archivo está en el mismo directorio que el código (puede cambiar fpathpara incluir el nombre de archivo y la ruta de carpeta adecuados).

En los dos ejemplos mencionados a continuación, la lista que desea viene dada por lst.

1.> Primer método :

fpath = 'dummy.txt'
with open(fpath, "r") as f: lst = [line.rstrip('\n \t') for line in f]

print lst
>>>['THIS IS LINE1.', 'THIS IS LINE2.', 'THIS IS LINE3.', 'THIS IS LINE4.']

2.> En el segundo método , uno puede usar el módulo csv.reader de la Biblioteca estándar de Python :

import csv
fpath = 'dummy.txt'
with open(fpath) as csv_file:
    csv_reader = csv.reader(csv_file, delimiter='   ')
    lst = [row[0] for row in csv_reader] 

print lst
>>>['THIS IS LINE1.', 'THIS IS LINE2.', 'THIS IS LINE3.', 'THIS IS LINE4.']

Puede usar cualquiera de los dos métodos. El tiempo necesario para la creación de lstes casi igual en los dos métodos.

Siddharth Satpathy
fuente
1
¿Cuál es la ventaja del segundo enfoque? ¿Por qué invocar una biblioteca adicional, que agrega casos extremos (el delimitador y las comillas)?
Charlie Harding
¿Para qué es el delimiter=' 'argumento?
AMC
2

Aquí hay una clase de biblioteca auxiliar Python (3) que uso para simplificar la E / S de archivos:

import os

# handle files using a callback method, prevents repetition
def _FileIO__file_handler(file_path, mode, callback = lambda f: None):
  f = open(file_path, mode)
  try:
    return callback(f)
  except Exception as e:
    raise IOError("Failed to %s file" % ["write to", "read from"][mode.lower() in "r rb r+".split(" ")])
  finally:
    f.close()


class FileIO:
  # return the contents of a file
  def read(file_path, mode = "r"):
    return __file_handler(file_path, mode, lambda rf: rf.read())

  # get the lines of a file
  def lines(file_path, mode = "r", filter_fn = lambda line: len(line) > 0):
    return [line for line in FileIO.read(file_path, mode).strip().split("\n") if filter_fn(line)]

  # create or update a file (NOTE: can also be used to replace a file's original content)
  def write(file_path, new_content, mode = "w"):
    return __file_handler(file_path, mode, lambda wf: wf.write(new_content))

  # delete a file (if it exists)
  def delete(file_path):
    return os.remove() if os.path.isfile(file_path) else None

Entonces usarías la FileIO.linesfunción, así:

file_ext_lines = FileIO.lines("./path/to/file.ext"):
for i, line in enumerate(file_ext_lines):
  print("Line {}: {}".format(i + 1, line))

Recuerde que los parámetros mode( "r"por defecto) y filter_fn(busca líneas vacías por defecto) son opcionales.

Incluso se puede quitar las read, writey los deletemétodos y acaba de salir de la FileIO.lines, o incluso convertirlo en un método separado llamado read_lines.

Rama Lógica
fuente
¿Es lines = FileIO.lines(path)realmente bastante más simple que with open(path) as f: lines = f.readlines()justificar la existencia de este ayudante? Estás ahorrando, como, 17 caracteres por llamada. (Y la mayoría de las veces, por razones de rendimiento y memoria, querrás recorrer un objeto de archivo directamente en lugar de leer sus líneas en una lista de todos modos, ¡así que ni siquiera querrás usar esto a menudo!) a menudo soy fanático de crear pequeñas funciones de utilidad, pero esta me parece que es innecesariamente crear una nueva forma de escribir algo que ya es corto y fácil con la biblioteca estándar que nos brinda.
Mark Amery
Además de lo que dijo @MarkAmery, ¿por qué usar una clase para esto?
AMC
1

Versión de línea de comando

#!/bin/python3
import os
import sys
abspath = os.path.abspath(__file__)
dname = os.path.dirname(abspath)
filename = dname + sys.argv[1]
arr = open(filename).read().split("\n") 
print(arr)

Corre con:

python3 somefile.py input_file_name.txt
jasonleonhard
fuente