2012-07-30 10 views
10

Meine Frage bezieht sich auf die Dateieingabe in Python mit open(). Ich habe eine Textdatei mytext.txt mit 3 Zeilen. Ich versuche, zwei Dinge mit dieser Datei zu tun: Drucken Sie die Zeilen und drucken Sie die Anzahl der Zeilen.Python Schleife durch die Eingabedatei

habe ich versucht, den folgenden Code:

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 

Ergebnis: es druckt die 3 Zeilen richtig, aber druckt "Anzahl der Zeilen: 0" (statt 3)


fand ich zwei Möglichkeiten, es zu lösen, und bekommen es 3 drucken:

1) ich verwende eine Schleife anstelle von zwei

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) nach der ersten Schleife, definiere ich input_file wieder

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 

Für mich scheint es, wie die Definition input_file = ... für nur einen Looping gültig ist, als ob es gelöscht wurde, nachdem ich es verwenden für eine Schleife. Aber ich verstehe nicht warum, wahrscheinlich ist es mir noch nicht 100% klar, wie variable = open(filename) in Python behandelt wird.

Übrigens sehe ich, dass es in diesem Fall besser ist, nur eine Schleife zu verwenden. Ich denke jedoch, dass ich diese Frage klären muss, da es Fälle geben kann, in denen ich sie nutzen kann/muss.

+0

Wenn Sie Zeilen verarbeiten wollen, warum verwenden nicht 'readlines()' – tMC

+3

readlines wird Ihre Maschine dreschen und möglicherweise zum Absturz bringen, wenn man es plötzlich mit einer großen Datei. Es ist normalerweise besser, Zeile für Zeile zu lesen. – user1277476

+0

Sie können auch readline() verwenden, die jeweils eine Zeile liest. Oder verwenden Sie den optionalen Größenhinweis-Parameter: readlines (Größenhinweis). Dadurch wird die Anzahl der gesamten Zeilen zurückgegeben, die in einen Puffer mit "Größenhinweis" passen. – ncultra

Antwort

19

Das Datei-Handle ist ein Iterator. Nach dem Durchlaufen der Datei wird der Zeiger an EOF (Ende der Datei) positioniert und der Iterator wird StopIteration auslösen, die die Schleife verlässt. Wenn Sie versuchen, einen Iterator für eine Datei zu verwenden, bei der der Zeiger auf EOF steht, wird StopIteration nur ausgelöst und beendet. Aus diesem Grund wird in der zweiten Schleife Null gezählt. Sie können den Dateizeiger mit input_file.seek(0) zurückspulen, ohne ihn erneut zu öffnen.

Das Zählen von Zeilen in der gleichen Schleife ist mehr E/A-effizient, sonst müssen Sie die gesamte Datei ein zweites Mal von der Festplatte lesen, nur um die Zeilen zu zählen. Dies ist ein sehr häufiges Muster:

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, das Datei-Objekt mit __enter__ und __exit__ ausgestattet worden, um die with statement interface zu adressieren.Dies ist syntaktischer Zucker für so etwas wie:

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) 

ich CPython denken schließt Datei-Handles, wenn sie Müll gesammelt, aber ich bin nicht sicher, ob dies für jede Implementierung gilt - IMHO ist es besser Praxis explizit schließen Ressource Griffe.

+0

Jetzt habe ich es. Vielen Dank! Übrigens, ich denke, es ist nicht spezifisch für Python, aber wahrscheinlich funktionieren die meisten Sprachen so. Es ist gut zu wissen. Danke noch einmal. –

5

Gibt es einen Grund, warum Sie könnten die folgende nicht verwenden:

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 

Die Sache durch offene zurückgegeben wird, ist ein Dateiobjekt. Dateiobjekte behalten ihre eigene interne Position bei, wenn Sie sie überlappen. Um das zu tun, was Sie zuerst versucht haben, müssen Sie es manuell zum Anfang zurückspulen, es wird nicht von selbst ausgeführt.

+0

Wie ich in meinem Beitrag erwähnt habe, weiß ich, dass dies ein besserer Weg ist. Der Grund meiner Post ist, dass ich das Verhalten von Python verstehen möchte, für das die erste Option nicht funktioniert. –

+0

Danke für die Erklärung, jetzt verstehe ich, wie es funktioniert. –

2

Versuchen Sie eine input_file.seek(0) zwischen den beiden Schleifen hinzuzufügen. Dadurch wird die Datei an den Anfang zurückgespult, sodass Sie sie erneut durchlaufen können.

0

Ich dünn das Modul fileinput willst du.

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