2009-03-03 8 views
2

Ich lese eine Datei in Python, wo jeder Datensatz durch eine leere neue Zeile getrennt ist. Wenn die Datei in zwei oder mehr Zeilen endet, wird der letzte Datensatz wie erwartet verarbeitet. Wenn die Datei jedoch in einer einzelnen neuen Zeile endet, wird sie nicht verarbeitet. Heres der Code:Die letzte neue Zeile beim Lesen einer Datei beibehalten

def fread(): 
    record = False 
    for line in open('somefile.txt'): 
     if line.startswith('Record'): 
      record = True 
      d = SomeObject() 

     # do some processing with line 
     d.process(line) 

     if not line.strip() and record: 
      yield d 
      record = False 

for record in fread(): 
    print(record) 

In dieser Datenprobe, funktioniert alles wie erwartet ('---' ist eine leere Zeile):

Aufnahme 1
Daten ein
Daten b
Daten c
\ n
Record 2
Daten a
Daten b
Daten c
\ n
\ n

Aber in diesem, isn't der letzte Datensatz zurückgegeben:

Aufnahme 1
Daten a
Daten b
Daten c
\ n
Datensatz 2
Daten a
Daten b
Daten c
\ n

Wie kann ich die letzte neue Zeile aus der Datei den letzten Datensatz zu erhalten bewahren?

PS .: Ich benutze den Begriff "bewahren", da ich keinen besseren Namen finden konnte.

Danke.

Bearbeiten Der ursprüngliche Code war eine bereinigte Version, nur um das Problem zu veranschaulichen, aber es scheint, dass ich zu viel abgestreift habe. Jetzt habe ich den Code aller Funktionen gepostet.

Ein wenig mehr Erklärung: Das Objekt SomeObject wird für jeden Datensatz in der Datei erstellt und die Datensätze werden durch leere neue Zeilen getrennt. Am Ende des Datensatzes gibt es das Objekt zurück, so dass ich es verwenden kann (in einem DB speichern, mit anderen Objekten vergleichen usw.).

Das Hauptproblem, wenn die Datei in einer einzelnen neuen Zeile endet, wird der letzte Datensatz nicht zurückgegeben. Es scheint, dass Python die letzte Zeile nicht liest, wenn sie leer ist.

Antwort

6

Die Art, wie es jetzt geschrieben ist, funktioniert wahrscheinlich sowieso nicht; Mit d = SomeObject() innerhalb Ihrer Schleife wird ein neues SomeObject für jede Zeile erstellt. Wenn ich jedoch richtig verstehe, wollen Sie, dass alle Zeilen zwischen leeren Zeilen zu diesem einen Objekt beitragen. Sie könnten stattdessen Folgendes tun:

Das ist kein großartiger Code, aber es funktioniert; Das letzte Objekt, das seine leere Zeile verfehlt, wird zurückgegeben, wenn die Schleife beendet ist.

+0

Sie haben richtig verstanden und ich habe meinen Beitrag bearbeitet, um klarer zu sehen, was ich möchte. Dein Ansatz ist sehr gut und löst mein Problem, vielen Dank, aber warum liest Python nicht die letzte Zeile, wenn sie leer ist? –

0

line.strip() führt zu einer leeren Zeichenfolge in einer leeren Zeile. Ein leerer String ist falsch, so schlucken Sie die leere Zeile

>>> bool("\n".strip()) 
False 
>>> bool("\n") 
True 
0

Wenn Sie readline (in einer Schleife) wiederholt aufrufen auf dem Dateiobjekt (statt mit in) sollte es funktionieren wie erwartet.Vergleichen Sie diese:

>>> x = open('/tmp/xyz') 
>>> x.readline() 
'x\n' 
>>> x.readline() 
'\n' 
>>> x.readline() 
'y\n' 
>>> x.readline() 
'' 
>>> open('/tmp/xyz').readlines() 
['x\n', '\n', 'y\n'] 
5

Sie könnten eine leichte Drehung in einer klassisch pythonic Richtung finden verbessert die predicability des Codes:

def fread(): 
    for line in open('text.txt'): 
     if line.strip(): 
      d = SomeObject() 
      yield d 

    raise StopIteration 

for record in fread(): 
    print record 

Der bevorzugte Weg, einen Generator in Python, wenn auch oft nicht streng beenden notwendig, ist mit der Ausnahme StopIteration. Die Verwendung von if line.strip() bedeutet einfach, dass Sie die Ausbeute erzielen, wenn nach dem Entfernen von Leerzeichen noch etwas in der Reihe bleibt. Die Konstruktion von SomeObject() kann überall sein ... Ich habe sie einfach verschoben, falls die Konstruktion von SomeObject teuer war oder Nebenwirkungen hatte, die nicht auftreten sollten, wenn die Zeile leer ist.

EDIT: Ich werde meine Antwort hier für die Nachwelt verlassen, aber DNS unten hat die ursprüngliche Absicht richtig, wo mehrere Zeilen zum gleichen SomeObject() - Datensatz (die ich total beschönigt) beitragen.

+0

Ihr Code entspricht zwar dem Code des Autors, aber aus dem Wortlaut seiner Frage und seinen Beispieldaten sieht es nicht so aus, als wolle er ein neues SomeObject in jeder nicht leeren Zeile erstellen. Er möchte, dass ein Zeilenblock zu einem SomeObject beiträgt. – DNS

+0

Ah ja .. du hast recht. –

+0

Hat meinen Beitrag bearbeitet, um auf Ihren zu verweisen, DNS. –

0

ersetzen open('somefile.txt'): mit open('somefile.txt').read().split('\n'): und Ihr Code wird funktionieren.

Aber Jarret Hardies Antwort ist besser.

+0

Ich kann nicht alle Dateien im Speicher lesen, es sind + 100k Zeilen. –

Verwandte Themen