2012-07-30 28 views
10

La mia domanda è relativa all'input di file in Python, utilizzando open(). Ho un file di testo mytext.txt con 3 linee. Sto cercando di fare due cose con questo file: stampare le linee e stampare il numero di linee.python looping attraverso il file di input

Ho provato il codice seguente:

input_file = open('mytext.txt', 'r') 
count_lines = 0 
for line in input_file: 
    print line 
for line in input_file: 
    count_lines += 1 
print 'number of lines:', count_lines 

risultati: esso stampa le 3 linee correttamente, ma stampa "numero di linee: 0" (invece di 3)


ho trovato due modi per risolverlo, e farlo stampare 3:

1) io uso un loop invece di due

input_file = open('mytext.txt', 'r') 
count_lines = 0 
for line in input_file: 
    print line 
    count_lines += 1 
print 'number of lines:', count_lines 

2) dopo il primo giro, mi definisco file_input nuovo

input_file = open('mytext.txt', 'r') 
count_lines = 0 
for line in input_file: 
    print line 
input_file = open('mytext.txt', 'r') 
for line in input_file: 
    count_lines += 1 
print 'number of lines:', count_lines 

A me, sembra che la definizione input_file = ... è valido per un solo looping, come se fosse stato eliminato dopo lo uso per un ciclo. Ma non capisco perché, probabilmente non è ancora chiaro al 100%, come sia stato trattato variable = open(filename) in Python.

A proposito, vedo che in questo caso è meglio utilizzare solo un ciclo. Tuttavia, sento di dover chiarire questa domanda, poiché potrebbero esserci casi in cui posso/devo farne uso.

+0

Se si desidera elaborare linee, perché non usare 'readlines()' – tMC

+3

readlines renderanno la vostra macchina thrash e possibilmente in crash se improvvisamente utilizza con un file di grandi dimensioni. Di solito è meglio leggere una riga alla volta. – user1277476

+0

puoi anche usare readline(), che legge una riga alla volta. O per evitare il thrashing/crash con readlines, usa il parametro opzionale hint size: readlines (suggerimento per la dimensione). Ciò restituirà il numero di intere righe che possono rientrare in un buffer di "suggerimento di dimensione". – ncultra

risposta

19

L'handle di file è un iteratore. Dopo aver eseguito l'iterazione sul file, il puntatore verrà posizionato su EOF (fine del file) e l'iteratore solleverà StopIteration che esce dal ciclo. Se si tenta di utilizzare un iteratore per un file in cui il puntatore si trova su EOF, esso solleverà StopIteration e verrà chiuso: per questo motivo conta zero nel secondo ciclo. È possibile riavvolgere il puntatore del file con input_file.seek(0) senza riaprirlo.

Detto questo, il conteggio delle linee nello stesso ciclo è più efficiente di I/O, altrimenti è necessario leggere l'intero file dal disco una seconda volta solo per contare le linee. Questo è un modello molto comune:

with open('filename.ext') as input_file: 
    for i, line in enumerate(input_file): 
     print line, 
print "{0} line(s) printed".format(i+1) 

In Python 2.5, l'oggetto file è stato dotato di __enter__ e __exit__ per affrontare il with statement interface.Questo è zucchero sintattico per qualcosa di simile:

input_file = open('filename.txt') 
try: 
    for i, line in enumerate(input_file): 
     print line, 
finally: 
    input_file.close() 
print "{0} line(s) printed".format(i+1) 

Penso CPython chiuderà handle di file quando ottengono garbage collection, ma non sono sicuro che questo vale per tutte le implementazioni - IMHO è meglio pratica chiusura esplicita risorsa maniglie.

+0

Ora ho capito. Grazie mille! A proposito, quindi penso che non sia qualcosa di specifico per Python, ma probabilmente la maggior parte delle lingue funziona così. È bello saperlo. Grazie ancora. –

5

C'è qualche motivo non è possibile utilizzare il seguente:

input_file = open('mytext.txt', 'r') 
count_lines = 0 
for line in input_file: 
    print line 
    count_lines += 1 
print 'number of lines:', count_lines 

La cosa restituiti da open è un oggetto file. Gli oggetti di file tengono traccia della loro posizione interna mentre li ricoprite, quindi per fare ciò che hai provato per primo, dovresti riavvolgerlo all'inizio manualmente, non lo farà da solo.

+0

Come ho detto nel mio post, so che questo è un modo migliore. Il motivo del mio post è che mi piacerebbe capire il comportamento di Python per il quale la prima opzione non funziona. –

+0

Grazie per la spiegazione, ora capisco come funziona. –

2

Provare ad aggiungere uno input_file.seek(0) tra i due anelli. Questo riavvolgerà il file all'inizio, in modo da poterlo ricopiare nuovamente.

0

Sottile il modulo fileinput desiderato.

Here is the link

if __name__ == "__main__": 
for line in fileinput.input(): 
    if fileinput.isfirstline(): 
     print("current file: %s" % fileinput.filename()) 

    print("line number: %d, current file number: %d" % 
      (fileinput.lineno(), fileinput.filelineno())) 
Problemi correlati