2009-05-05 12 views
21

Ich schreibe ein Skript, das Fehler von einem anderen Programm protokolliert und das Programm dort neu startet, wo es einen Fehler festgestellt hat. Aus welchen Gründen auch immer, die Entwickler dieses Programms hielten es nicht für notwendig, diese Funktionalität standardmäßig in ihr Programm aufzunehmen.Mischen von Dateien und Schleifen

Wie auch immer, das Programm nimmt eine Eingabedatei, analysiert sie und erstellt eine Ausgabedatei. Die Eingabedatei ist in einem bestimmten Format:

UI - 26474845 
TI - the title (can be any number of lines) 
AB - the abstract (can also be any number of lines) 

Wenn das Programm einen Fehler wirft, es gibt Ihnen die Referenzinformationen benötigen Sie den Fehler verfolgen - nämlich die UI, welcher Abschnitt (Titel oder Zusammenfassung), und die Zeilennummer relativ zum Beginn des Titels oder der Zusammenfassung. Ich möchte die fehlerhaften Sätze aus der Eingabedatei mit einer Funktion protokollieren, die die Referenznummer und die Datei nimmt, den Satz findet und protokolliert. Der beste Weg, um darüber nachzudenken, besteht darin, die Datei eine bestimmte Anzahl von Malen vorwärts zu bewegen (n-mal, wobei n die Zeilennummer relativ zum Anfang des Sections ist). Die Art und Weise, den Sinn schien zu machen, dies zu tun ist:

i = 1 
while i <= lineNumber: 
    print original.readline() 
    i += 1 

Ich sehe nicht, wie dies würde ich Daten verlieren, aber Python denkt, es würde und sagt ValueError: Mixing iteration and read methods would lose data. Weiß jemand, wie man das richtig macht?

+1

-1: Code aus dem Snippet fehlt. Es gibt wahrscheinlich ein "für etwas im Original:", das im gezeigten Code fehlt. –

Antwort

44

Sie erhalten den ValueError, weil Ihr Code wahrscheinlich for line in original: neben original.readline() hat. Eine einfache Lösung, die das Problem behebt, ohne das Programm langsamer zu machen oder mehr Speicher verbrauchen

Ändern
for line in original: 
    ... 

zu

while True: 
    line = original.readline() 
    if not line: break 
    ... 
+1

Sie haben den Nagel auf den Kopf getroffen - ich * * benutze für, als auch während. Das war die schnellste Lösung. Danke und danke für die Antworten aller anderen. –

+0

hat mir auch geholfen. Danke. – nish

+0

Dies scheint nicht zu funktionieren. Es kommt in eine Endlosschleife. Ich glaube, der eof gibt keinen None-Wert zurück. – lionel319

10

Verwenden Sie for und enumerate.

Beispiel:

for line_num, line in enumerate(file): 
    if line_num < cut_off: 
     print line 

HINWEIS: Das Sie bereits davon ausgegangen, reinigen Sie Ihren Datei-Handles up usw.

Auch die takewhile Funktion könnte als nützlich erweisen, wenn Sie einen funktionellen Geschmack bevorzugen.

0

Sie nur eine Zeile benötigt Unter der Annahme, könnte dies hilfreich sein

import itertools 

def getline(fobj, line_no): 
    "Return a (1-based) line from a file object" 
    return itertools.islice(fobj, line_no-1, line_no).next() # 1-based! 

>>> print getline(open("/etc/passwd", "r"), 4) 
'adm:x:3:4:adm:/var/adm:/bin/false\n' 

Sie können StopIterationsfehler abfangen (wenn die Datei weniger Zeilen enthält).

0

Hier ist eine Version ohne die hässlichen while True Muster und ohne andere Module:

for line in iter(original.readline, ''): 
    if …: # to the beginning of the title or abstract 
     for i in range(lineNumber): 
      print original.readline(), 
     break