Come leggere un file riga per riga in un elenco?


2027

Come faccio a leggere ogni riga di un file in Python e memorizzare ogni riga come elemento in un elenco?

Voglio leggere il file riga per riga e aggiungere ogni riga alla fine dell'elenco.

Risposte:


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] 

206
Non usare file.readlines()in for-loop, è sufficiente un oggetto file:lines = [line.rstrip('\n') for line in file]
jfs

88
Nel caso in cui lavori con Big Data l'utilizzo readlines()non è molto efficiente in quanto può causare MemoryError . In questo caso è meglio scorrere il file usando for line in f:e lavorando con ciascuna linevariabile.
DarkCygnus,

7
Ho controllato il profilo di memoria in diversi modi indicati nelle risposte usando la procedura qui menzionata . L'uso della memoria è di gran lunga migliore quando ogni riga viene letta dal file ed elaborata, come suggerito da @DevShark qui . Tenere tutte le righe in un oggetto di raccolta non è una buona idea se la memoria è un vincolo o il file è grande. Il tempo di esecuzione è simile in entrambi gli approcci.
Tirtha R

6
Inoltre, .rstrip()funzionerà leggermente più velocemente se si rimuovono gli spazi bianchi dalle estremità delle linee.
Gringo Suave,

Oneliner:with open(filename) as f: content = [i.strip() for i in f.readlines()]
Vishal Gupta

1002

Vedi Input e Ouput :

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

o togliendo il carattere newline:

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

12
Meglio, usare f.read().splitlines(), che rimuove le nuove righe
Segna il

La seconda versione è for line in open(filename)sicura? Cioè, il file verrà chiuso automaticamente?
becko,

2
Meglio leggere il file una riga alla volta anziché leggere l'intero file in memoria tutto in una volta. Ciò non si adatta bene con file di input di grandi dimensioni. Vedi sotto la risposta di Robert.
Brad Hein

1
lines = [x.rstrip('\n') for x in open('data\hsf.txt','r')]Se scrivo in questo modo, come posso chiudere il file dopo averlo letto?
Ramisa Anjum Aditi,

2
Sì, al punto che altri stanno facendo qui, mentre non è "best practice" da usare opensenza il gestore del contesto (o qualche altro modo garantito per chiuderlo), questo non è davvero uno di quei casi - quando l'oggetto non ha più riferimenti verrà raccolto e il file verrà chiuso, cosa che dovrebbe accadere immediatamente in caso di errore o meno, quando l'elaborazione della comprensione dell'elenco è terminata.
Aaron Hall

579

Questo è più esplicito del necessario, ma fa quello che vuoi.

with open("file.txt") as file_in:
    lines = []
    for line in file_in:
        lines.append(line)

18
Preferisco questa risposta poiché non richiede di caricare l'intero file in memoria (in questo caso è comunque aggiunto array, ma potrebbero esserci altre circostanze). Certamente per file di grandi dimensioni questo approccio potrebbe mitigare i problemi.
JohannesB,

1
L'aggiunta a un array è lenta. Non riesco a pensare a un caso d'uso in cui questa è la soluzione migliore.
Elias Strehle,

@haccks è meglio perché non carica l'intero file in memoria o c'è di più?
OrigamiEye

4
Nota: questa soluzione non elimina le nuove righe.
AMC

1
Questa soluzione carica l'intero file in memoria. Non so perché la gente pensi che non lo sia.
andrebrait

274

Ciò produrrà un "array" di righe dal file.

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

openrestituisce un file che può essere ripetuto. Quando si scorre su un file, si ottengono le righe da quel file. tuplepuò prendere un iteratore e creare un'istanza di tupla dall'iteratore che gli dai. linesè una tupla creata dalle righe del file.


31
@MarshallFarrier Try lines = open(filename).read().split('\n')invece.
Noctis Skytower,

16
chiude il file?
Vanuan,

5
@Vanuan Poiché non vi è alcun riferimento rimanente al file dopo l'esecuzione della riga, il distruttore dovrebbe chiudere automaticamente il file.
Noctis Skytower,

30
@NoctisSkytower Trovo lines = open(filename).read().splitlines()un po 'più pulito e credo che gestisca meglio anche le terminazioni di linea DOS.
Jay

8
@ mklement0 Supponendo un file di 1000 righe, a listoccupa circa il 13,22% di spazio in più rispetto a a tuple. I risultati provengono da from sys import getsizeof as g; i = [None] * 1000; round((g(list(i)) / g(tuple(i)) - 1) * 100, 2). La creazione di un tuplerichiede circa il 4,17% in più rispetto alla creazione di list(con una deviazione standard dello 0,16%). I risultati vengono eseguiti from timeit import timeit as t; round((t('tuple(i)', 'i = [None] * 1000') / t('list(i)', 'i = [None] * 1000') - 1) * 100, 2)30 volte. La mia soluzione favorisce lo spazio rispetto alla velocità quando la necessità di mutabilità è sconosciuta.
Noctis Skytower,

194

Se si desidera \nincludere:

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

Se non si desidera \nincludere:

with open(fname) as f:
    content = f.read().splitlines()

168

Secondo i Metodi di oggetti file di Python , il modo più semplice per convertire un file di testo in un listè:

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

Se hai solo bisogno di scorrere le righe dei file di testo, puoi usare:

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

Vecchia risposta:

Utilizzando withe readlines():

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

Se non ti interessa chiudere il file, questo one-liner funziona:

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

Il modo tradizionale :

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

150

Potresti semplicemente fare quanto segue, come è stato suggerito:

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

Si noti che questo approccio ha 2 aspetti negativi:

1) Memorizzi tutte le linee in memoria. Nel caso generale, questa è una pessima idea. Il file potrebbe essere molto grande e potresti esaurire la memoria. Anche se non è grande, è semplicemente uno spreco di memoria.

2) Ciò non consente l'elaborazione di ogni riga durante la lettura. Quindi, se si elaborano le linee dopo questo, non è efficiente (richiede due passaggi anziché uno).

Un approccio migliore per il caso generale sarebbe il seguente:

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

Dove si definisce la funzione di processo nel modo desiderato. Per esempio:

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

(L'implementazione della Supermanlezione è lasciata come esercizio per te).

Funzionerà bene per qualsiasi dimensione di file e passerai attraverso il tuo file in 1 solo passaggio. Questo è in genere il modo in cui funzionano i parser generici.


5
Questo era esattamente ciò di cui avevo bisogno - e grazie per aver spiegato gli aspetti negativi. Come principiante in Python, è fantastico capire perché una soluzione è la soluzione. Saluti!
Ephexx,

5
Pensa un po 'di più a Corey. Vuoi davvero che il tuo computer legga ogni riga, senza mai fare nulla con queste righe? Sicuramente puoi capire che devi sempre elaborarli in un modo o nell'altro.
DevShark il

5
Devi sempre fare qualcosa con le linee. Può essere semplice come stampare le linee o contarle. Non ha alcun valore avere il processo di leggere le righe in memoria, ma non farci nulla.
DevShark,

2
Devi sempre fare qualcosa con loro. Penso che il punto che stai cercando di sottolineare sia che potresti voler applicare una funzione a tutti contemporaneamente, piuttosto che uno per uno. Questo è davvero il caso a volte. Ma è molto inefficiente dal punto di vista della memoria farlo, e ti impedisce di leggere i file se la sua impronta è più grande del tuo Ram. Ecco perché in genere i parser generici funzionano nel modo che ho descritto.
DevShark,

2
@PierreOcinom che è corretto. Dato che il file è aperto in modalità di sola lettura, non è possibile modificare il file originale con il codice sopra. Per aprire un file sia per la lettura che per la scrittura, utilizzareopen('file_path', 'r+')
DevShark

66

Dati nell'elenco

Supponiamo di avere un file di testo con i nostri dati come nelle righe seguenti,

Contenuto del file di testo:

line 1
line 2
line 3
  • Apri il cmd nella stessa directory (fai clic con il pulsante destro del mouse e scegli cmd o PowerShell)
  • Esegui pythone nell'interprete scrivi:

Lo script 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']

Utilizzando 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)

produzione:

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']

1
read().splitlines()ti viene fornito da Python: è semplicemente readlines()(che è probabilmente più veloce, in quanto è meno dispendioso).
Eric O Lebigot,

1
@EricOLebigot dagli esempi mostrati, sembra read().splitlines()e readlines()non produce lo stesso output. Sei sicuro che siano equivalenti?
Iraq

1
Se usi solo readline, devi usare il metodo strip per sbarazzarmi del \ n nel testo, quindi ho modificato gli ultimi esempi usando una comprensione dell'elenco per avere lo stesso output in entrambi i casi. Quindi, se usi read (). Readlines () avrai un oggetto "pulito" con la riga e senza il carattere newline, altrimenti devi fare quello che vedi nel codice sopra.
Giovanni G. PY il

1
Infatti. Si noti che nel codice soprattutto strip()devono essere rstrip("\n")eliminati gli spazi attorno a una riga. Inoltre, non ha senso fare readlines()una comprensione dell'elenco: è semplicemente iterare il file, poiché non perde tempo e memoria creando un elenco intermedio delle righe.
Eric O Lebigot

1
@EricOLebigot Fatto, grazie.
Giovanni G. PY

43

Per leggere un file in un elenco devi fare tre cose:

  • Apri il file
  • Leggi il file
  • Memorizza i contenuti come elenco

Fortunatamente Python rende molto semplice fare queste cose, quindi il modo più breve per leggere un file in un elenco è:

lst = list(open(filename))

Comunque aggiungerò qualche spiegazione in più.

Aprire il file

Presumo che tu voglia aprire un file specifico e non ti occupi direttamente di un handle di file (o di un handle simile a un file). La funzione più comunemente usata per aprire un file in Python è open, richiede un argomento obbligatorio e due opzionali in Python 2.7:

  • Nome del file
  • Modalità
  • Buffering (ignorerò questo argomento in questa risposta)

Il nome file deve essere una stringa che rappresenta il percorso del file . Per esempio:

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)

Si noti che l'estensione del file deve essere specificata. Ciò è particolarmente importante per gli utenti di Windows perché estensioni di file come .txto .doc, ecc. Sono nascoste per impostazione predefinita quando vengono visualizzate in Explorer.

Il secondo argomento è il mode, è di rdefault che significa "sola lettura". Questo è esattamente ciò di cui hai bisogno nel tuo caso.

Ma nel caso in cui desideri effettivamente creare un file e / o scrivere in un file, avrai bisogno di un argomento diverso qui. C'è una risposta eccellente se vuoi una visione d'insieme .

Per leggere un file puoi ometterlo modeo passarlo esplicitamente:

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

Entrambi apriranno il file in modalità di sola lettura. Nel caso in cui si desideri leggere in un file binario su Windows, è necessario utilizzare la modalità rb:

open(filename, 'rb')

Su altre piattaforme la 'b'(modalità binaria) viene semplicemente ignorata.


Ora che ho mostrato come fare openal file, parliamo del fatto che ne hai sempre bisogno close. Altrimenti manterrà un handle di file aperto sul file fino a quando il processo non termina (o Python configura l'handle di file).

Mentre potresti usare:

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

Ciò non riuscirà a chiudere il file quando qualcosa tra opene closegenera un'eccezione. Puoi evitarlo usando a trye finally:

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

Tuttavia Python fornisce gestori di contesto che hanno una sintassi più carina (ma per openquasi identica alla trye finallysopra):

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

L'ultimo approccio è l' approccio consigliato per aprire un file in Python!

Lettura del file

Okay, hai aperto il file, ora come leggerlo?

La openfunzione restituisce un fileoggetto e supporta il protocollo di iterazione di Pythons. Ogni iterazione ti darà una linea:

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

Questo stamperà ogni riga del file. Nota comunque che ogni riga conterrà un carattere di nuova riga \nalla fine (potresti voler verificare se il tuo Python è costruito con il supporto universale di nuove righe , altrimenti potresti anche avere \r\nWindows o \rMac come nuove righe). Se non lo desideri, puoi semplicemente rimuovere l'ultimo carattere (o gli ultimi due caratteri su Windows):

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

Ma l'ultima riga non ha necessariamente una nuova riga finale, quindi non si dovrebbe usare quella. Si potrebbe verificare se termina con una nuova riga finale e in tal caso rimuoverla:

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

Ma potresti semplicemente rimuovere tutti gli spazi bianchi (incluso il \ncarattere) dalla fine della stringa , questo rimuoverà anche tutti gli altri spazi bianchi finali quindi devi fare attenzione se questi sono importanti:

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

Tuttavia, se le linee terminano con \r\n("newline" di Windows), questo si .rstrip()occuperà anche del \r!

Memorizza i contenuti come elenco

Ora che sai come aprire il file e leggerlo, è il momento di archiviare i contenuti in un elenco. L'opzione più semplice sarebbe quella di utilizzare la listfunzione:

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

Nel caso in cui si desideri eliminare le nuove righe finali, è possibile utilizzare una comprensione elenco:

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

O ancora più semplice: il .readlines()metodo filedell'oggetto per impostazione predefinita restituisce una listdelle righe:

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

Ciò includerà anche i caratteri di nuova riga finali, se non li vuoi consiglierei l' [line.rstrip() for line in f]approccio perché evita di mantenere due elenchi contenenti tutte le righe in memoria.

C'è un'opzione aggiuntiva per ottenere l'output desiderato, tuttavia è piuttosto "non ottimale": readil file completo in una stringa e quindi diviso su newline:

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

o:

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

Questi si occupano automaticamente delle nuove righe finali perché il splitpersonaggio non è incluso. Tuttavia non sono ideali perché mantieni il file come stringa e come un elenco di righe in memoria!

Sommario

  • Utilizzare with open(...) as fquando si aprono i file perché non è necessario occuparsi della chiusura del file e si chiude il file anche se si verifica un'eccezione.
  • filegli oggetti supportano il protocollo di iterazione, quindi leggere un file riga per riga è semplice come for line in the_file_object:.
  • Sfoglia sempre la documentazione per le funzioni / classi disponibili. Il più delle volte c'è una corrispondenza perfetta per l'attività o almeno una o due buone. La scelta ovvia in questo caso sarebbe readlines()ma se si desidera elaborare le righe prima di memorizzarle nell'elenco, consiglierei una semplice comprensione dell'elenco.

L'ultimo approccio è l'approccio consigliato per aprire un file in Python! Perché è l'ultimo, quindi? La stragrande maggioranza delle persone non dà un'occhiata alle prime righe di una risposta prima di passare?
AMC

@AMC Non ci ho pensato molto quando ho scritto la risposta. Pensi che dovrei metterlo in cima alla risposta?
MSeifert

Potrebbe essere meglio, sì. Ho anche notato che hai menzionato Python 2, in modo da poterlo aggiornare anche.
AMC

Ah, la domanda era originariamente taggata python-2.x. Potrebbe avere senso aggiornarlo più in generale. Vedrò se ci arriverò la prossima volta. Grazie per i vostri suggerimenti. Molto apprezzato!
MSeifert

42

Modo pulito e pitonico di leggere le righe di un file in un elenco


Innanzitutto, dovresti concentrarti sull'apertura del tuo file e sulla lettura del suo contenuto in modo efficiente e pitonico. Ecco un esempio del modo in cui personalmente NON preferisco:

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.

Preferisco invece il metodo seguente per aprire i file sia in lettura che in scrittura poiché è molto pulito e non richiede un ulteriore passaggio per chiudere il file una volta terminato di usarlo. Nell'istruzione seguente, apriamo il file per la lettura e lo assegniamo alla variabile "infile". Al termine dell'esecuzione del codice all'interno di questa istruzione, il file verrà automaticamente chiuso.

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

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

Ora dobbiamo concentrarci sul portare questi dati in un Elenco Python perché sono iterabili, efficienti e flessibili. Nel tuo caso, l'obiettivo desiderato è quello di portare ogni riga del file di testo in un elemento separato. Per fare ciò, useremo il metodo splitlines () come segue:

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

Il prodotto finale:

# 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()

Test del nostro codice:

  • Contenuto del file di testo:
     A fost odatã ca-n povesti,
     A fost ca niciodatã,
     Din rude mãri împãrãtesti,
     O prea frumoasã fatã.
  • Dichiarazioni di stampa a scopo di test:
    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]
  • Output (aspetto diverso a causa dei caratteri 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ã.

30

Introdotto in Python 3.4, pathlibha un metodo davvero conveniente per leggere testo da file, come segue:

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

(La splitlineschiamata è ciò che la trasforma da una stringa contenente l'intero contenuto del file in un elenco di righe nel file).

pathlibha molte comodità a portata di mano. read_textè carino e conciso e non devi preoccuparti di aprire e chiudere il file. Se tutto ciò che devi fare con il file è leggere tutto in una volta, è una buona scelta.


29

Ecco un'altra opzione usando la comprensione dell'elenco sui file;

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

Questo dovrebbe essere un modo più efficiente poiché la maggior parte del lavoro viene svolto all'interno dell'interprete Python.


10
rstrip()potenzialmente spoglia tutto lo spazio bianco finale, non solo il \n; usare .rstrip('\n').
mklement0

Ciò non garantisce inoltre che il file verrà chiuso dopo la lettura in tutte le implementazioni di Python (sebbene in CPython, l'implementazione principale di Python, lo sarà).
Mark Amery,

1
Questo dovrebbe essere un modo più efficiente poiché la maggior parte del lavoro viene svolto all'interno dell'interprete Python. Cosa significa?
AMC

28
f = open("your_file.txt",'r')
out = f.readlines() # will append in the list out

Ora variabile out è un elenco (array) di ciò che si desidera. Puoi fare:

for line in out:
    print (line)

O:

for line in f:
    print (line)

Otterrai gli stessi risultati.


27

Leggere e scrivere file di testo con Python 2 e Python 3; funziona 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)

Cose da notare:

  • withè un cosiddetto gestore di contesto . Si assicura che il file aperto venga nuovamente chiuso.
  • Tutte le soluzioni qui che semplicemente fanno .strip()o.rstrip() non riescono a riprodurle linescome anche spogliano lo spazio bianco.

Terminazioni di file comuni

.txt

Scrittura / lettura di file più avanzata

Per la tua applicazione, potrebbe essere importante quanto segue:

  • Supporto da altri linguaggi di programmazione
  • Performance di lettura / scrittura
  • Compattezza (dimensione del file)

Vedi anche: Confronto dei formati di serializzazione dei dati

Nel caso in cui tu stia cercando un modo per creare file di configurazione, potresti voler leggere il mio breve articolo File di configurazione in Python .


26

Un'altra opzione è numpy.genfromtxt, ad esempio:

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

Questo renderà dataun array NumPy con tutte le righe quante sono nel tuo file.


25

Se desideri leggere un file dalla riga di comando o da stdin, puoi anche utilizzare il fileinputmodulo:

# reader.py
import fileinput

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

fileinput.close()

Passa i file in questo modo:

$ python reader.py textfile.txt 

Maggiori informazioni qui: http://docs.python.org/2/library/fileinput.html


20

Il modo più semplice per farlo

Un modo semplice è:

  1. Leggi l'intero file come una stringa
  2. Dividi la stringa riga per riga

In una riga, ciò darebbe:

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

Tuttavia, questo è un modo abbastanza inefficiente in quanto memorizzerà 2 versioni del contenuto in memoria (probabilmente non è un grosso problema per i file di piccole dimensioni, ma comunque). [Grazie Mark Amery].

Esistono 2 modi più semplici:

  1. Utilizzo del file come iteratore
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. Se si utilizza Python 3.4 o versioni successive, utilizzare meglio pathlibper creare un percorso per il file che è possibile utilizzare per altre operazioni nel programma:
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()]

Questo è un cattivo approccio. Per prima cosa, chiamare .read().splitlines()non è in alcun modo "più semplice" della semplice chiamata .readlines(). Per un altro, è inefficiente dalla memoria; stai inutilmente memorizzando due versioni del contenuto del file (la singola stringa restituita da .read()e l'elenco delle stringhe restituite da splitlines()) in memoria contemporaneamente.
Mark Amery,

@MarkAmery True. Grazie per averlo evidenziato. Ho aggiornato la mia risposta.
Jean-Francois T.

14

Basta usare le funzioni splitlines (). Ecco un esempio

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

Nell'output avrai l'elenco delle righe.


Memoria inefficiente rispetto all'utilizzo .readlines(). Questo mette in memoria due copie del contenuto del file contemporaneamente (una come una singola stringa enorme, una come un elenco di righe).
Mark Amery,

11

Se vuoi confrontarti con un file molto grande / enorme e vuoi leggere più velocemente (immagina di essere in una competizione di codifica Topcoder / Hackerrank), potresti leggere una porzione di linee considerevolmente più grande in un buffer di memoria contemporaneamente, piuttosto che iterare riga per riga a livello di file.

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)

cosa fa process (line)? Ottengo un errore che non esiste una variabile così definita. Immagino che qualcosa abbia bisogno di essere importato e ho provato a importare multiprocessing. Processo, ma non è questo credo. Potresti per favore elaborare? Grazie
Newskooler il

1
process(line)è una funzione che è necessario implementare per elaborare i dati. ad esempio, invece di quella riga, se si utilizza print(line), verrà stampata ogni riga da lines_buffer.
Khanal,

f.readlines (buffersize) restituisce un buffer immutabile. se vuoi leggere direttamente nel tuo buffer devi usare la funzione readinto (). Sarò molto più veloce.
David Dehghan,

7

I modi più semplici per farlo con alcuni vantaggi aggiuntivi sono:

lines = list(open('filename'))

o

lines = tuple(open('filename'))

o

lines = set(open('filename'))

Nel caso di set, dobbiamo ricordare che non abbiamo l'ordine delle righe conservato e ci liberiamo delle linee duplicate.

Di seguito ho aggiunto un importante supplemento di @MarkAmery :

Poiché non stai invocando .closel'oggetto file né stai usando withun'istruzione, in alcune implementazioni di Python il file potrebbe non chiudersi dopo la lettura e il tuo processo perderà un handle di file aperto .

In CPython (la normale implementazione di Python utilizzata dalla maggior parte delle persone), questo non è un problema poiché l'oggetto file verrà immediatamente raccolto in modo inutile e questo chiuderà il file, ma è comunque generalmente considerata la migliore pratica fare qualcosa del tipo :

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

per garantire che il file venga chiuso indipendentemente dall'implementazione di Python in uso.


1
Dato che non stai invocando .closel'oggetto file né stai usando withun'istruzione, in alcune implementazioni di Python il file potrebbe non chiudersi dopo la lettura e il tuo processo perderà un handle di file aperto. In CPython (la normale implementazione di Python utilizzata dalla maggior parte delle persone), questo non è un problema poiché l'oggetto file verrà immediatamente raccolto in modo inutile e questo chiuderà il file, ma è comunque generalmente considerata la migliore pratica fare qualcosa del genere with open('filename') as f: lines = list(f)per assicurarsi che il file viene chiuso indipendentemente dall'implementazione di Python in uso.
Mark Amery,

Grazie per il tuo fantastico commento @MarkAmery! Lo apprezzo molto.
simhumileco,

1
@simhumileco Perché la migliore (corretta) soluzione è l'ultima?
AMC

@AMC perché prima, volevo mostrare i modi più semplici e per coerenza di ragionamento.
simhumileco

Inoltre, spero che la mia risposta sia fatta in modo che sia breve e facile da leggere.
simhumileco

4

Usa questo:

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

dataè un tipo di frame di dati e utilizza i valori per ottenere ndarray. Puoi anche ottenere un elenco usando array.tolist().


pandas.read_csv()è per leggere i dati CSV , come è appropriato qui?
AMC

4

Schema e riepilogo

Con a filename, gestendo il file da un Path(filename)oggetto o direttamente con open(filename) as f, eseguire una delle seguenti operazioni:

  • list(fileinput.input(filename))
  • usando with path.open() as f, chiamaf.readlines()
  • list(f)
  • path.read_text().splitlines()
  • path.read_text().splitlines(keepends=True)
  • iterare su fileinput.inputo fe list.appendogni riga una alla volta
  • passare fa un list.extendmetodo associato
  • utilizzare fnella comprensione di un elenco

Spiego il caso d'uso per ciascuno di seguito.

In Python, come posso leggere un file riga per riga?

Questa è un'ottima domanda Innanzitutto, creiamo alcuni dati di esempio:

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

Gli oggetti file sono iteratori pigri, quindi basta scorrere su di esso.

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

In alternativa, se hai più file, usa fileinput.inputun altro iteratore pigro. Con un solo file:

import fileinput

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

o per più file, passagli un elenco di nomi di file:

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

Ancora una volta, fe fileinput.inputsoprattutto entrambi sono / return iteratori pigri. Puoi usare un iteratore solo una volta, quindi per fornire un codice funzionale evitando la verbosità userò un po 'più conciso il fileinput.input(filename)punto di partenza.

In Python, come posso leggere un file riga per riga in un elenco?

Ah, ma lo vuoi in un elenco per qualche motivo? Lo eviterei se possibile. Ma se insistete ... basta passare il risultato di fileinput.input(filename)a list:

list(fileinput.input(filename))

Un'altra risposta diretta è chiamare f.readlines, che restituisce il contenuto del file (fino a un hintnumero opzionale di caratteri, in modo da poterlo fare suddividere in più elenchi in quel modo).

È possibile accedere a questo oggetto file in due modi. Un modo è passare il nome file al openbuiltin:

filename = 'filename'

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

o usando il nuovo oggetto Path dal pathlibmodulo (di cui mi sono molto affezionato e che userò da qui in poi):

from pathlib import Path

path = Path(filename)

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

list consumerà anche l'iteratore di file e restituirà un elenco - anche un metodo abbastanza diretto:

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

Se non ti dispiace leggere l'intero testo in memoria come una singola stringa prima di dividerlo, puoi farlo come una riga con l' Pathoggetto e il splitlines()metodo stringa. Per impostazione predefinita, splitlinesrimuove le nuove righe:

path.read_text().splitlines()

Se vuoi mantenere le nuove righe, passa keepends=True:

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

Voglio leggere il file riga per riga e aggiungere ogni riga alla fine dell'elenco.

Ora questo è un po 'sciocco da chiedere, dato che abbiamo dimostrato facilmente il risultato finale con diversi metodi. Ma potresti dover filtrare o operare sulle linee mentre fai la tua lista, quindi umorizziamo questa richiesta.

L'utilizzo list.appendti consentirebbe di filtrare o operare su ogni riga prima di aggiungerlo:

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

line_list

L'uso list.extendsarebbe un po 'più diretto e forse utile se si dispone di un elenco preesistente:

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

O più idiomaticamente, potremmo invece usare una comprensione dell'elenco e mappare e filtrare al suo interno, se desiderabile:

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

O ancora più direttamente, per chiudere il cerchio, basta passarlo all'elenco per creare un nuovo elenco direttamente senza operare sulle linee:

list(fileinput.input(filename))

Conclusione

Hai visto molti modi per ottenere linee da un file in un elenco, ma ti consiglio di evitare di materializzare grandi quantità di dati in un elenco e utilizzare invece l'iterazione lenta di Python per elaborare i dati, se possibile.

Cioè, preferisci fileinput.inputo with path.open() as f.


4

Nel caso in cui ci siano anche righe vuote nel documento, mi piace leggere il contenuto e passarlo attraverso filterper evitare elementi stringa vuoti

with open(myFile, "r") as f:
    excludeFileContent = list(filter(None, f.read().splitlines()))

1
Questo non è ritmico, fai attenzione.
AMC

3

Puoi anche usare il comando loadtxt in NumPy. Questo controlla meno condizioni rispetto a genfromtxt, quindi potrebbe essere più veloce.

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

2

Mi piace usare quanto segue. Leggendo le righe immediatamente.

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

O usando la comprensione dell'elenco:

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

2
Non è necessario readlines(), il che comporta anche una penalità di memoria. Puoi semplicemente rimuoverlo, poiché iterando su un file (di testo) vengono visualizzate le righe a turno.
Eric O Lebigot,

2
È necessario utilizzare withun'istruzione per aprire (e chiudere implicitamente) il file.
Aran-Fey,

2

Vorrei provare uno dei metodi di seguito indicati. Il file di esempio che uso ha il nome dummy.txt. Puoi trovare il file qui . Presumo che il file si trovi nella stessa directory del codice (è possibile modificare fpathper includere il nome file e il percorso della cartella corretti).

In entrambi gli esempi di seguito elencati, viene fornito l'elenco desiderato lst.

1.> Primo metodo :

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.> Nel secondo metodo , è possibile utilizzare il modulo csv.reader dalla libreria standard di 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.']

È possibile utilizzare uno dei due metodi. Il tempo impiegato per la creazione di lstè quasi uguale nei due metodi.


1
Qual è il vantaggio del secondo approccio? Perché invocare una libreria aggiuntiva, che aggiunge casi limite (il delimitatore e le virgolette)?
Charlie Harding

A cosa serve l' delimiter=' 'argomento?
AMC

2

Ecco una classe di libreria di supporto Python (3) che utilizzo per semplificare l'I / O dei file:

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

Dovresti quindi utilizzare la FileIO.linesfunzione, in questo modo:

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

Ricorda che mode( "r"per impostazione predefinita) efilter_fn parametri (verifica le righe vuote per impostazione predefinita) sono facoltativi.

Si potrebbe anche rimuovere le read, writee deletemetodi e lasciare solo la FileIO.lines, o anche trasformarlo in un metodo separato chiamato read_lines.


È lines = FileIO.lines(path)davvero abbastanza più semplice che with open(path) as f: lines = f.readlines()giustificare l'esistenza di questo aiutante? Stai risparmiando, ad esempio, 17 caratteri per chiamata. (E la maggior parte delle volte, per motivi di prestazioni e memoria, ti consigliamo di eseguire il loop su un oggetto file direttamente anziché leggere comunque le sue righe in un elenco, quindi non vorrai nemmeno usarlo spesso!) spesso sono un fan della creazione di piccole funzioni di utilità, ma questa mi sembra che stia semplicemente creando un nuovo modo di scrivere qualcosa che è già breve e facile con la libreria standard.
Mark Amery,

Oltre a ciò che ha detto @MarkAmery, perché usare una classe per questo?
AMC

1

Versione da riga di 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)

Corri con:

python3 somefile.py input_file_name.txt
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.