Nur die letzten x Zeilen aus Datei auslesn

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
FFly82
User
Beiträge: 2
Registriert: Freitag 14. November 2014, 18:00

Hallo. Ich bin neu hier und komme mit einem kleinen Script nicht weiter welces ich für meinen Raspberry schreibe

Und zwar speicher ich per CronJob einmal pro Stunde ein paar Zahlenwerte in eine Datei.

Code: Alles auswählen

.......
13.11.14-10:00;15;19
13.11.14-12:00;4;23
13.11.14-14:00;35;21
13.11.14-16:00;71;17
......
Danach soll per Script aus dieser Datei eine Grafik erstellt werden Dies funktioniert auch soweit alles ganz gut.

Nur werden mit der Zeit immer mehr Daten in der Datei gespeichert (die Daten brauch ich evt erneut, so das ich diese nicht löschen will/kann)
Die Grafik soll aber nur die Daten der letzten 20 Zeilen erstellen.

Nun stellt sich mir die Frage wie ich es schaffe das eben nur diese Zeilen ausgelesen werden?

Hier mein Code der bislang läuft aber halt die komplette Datei einliest:

Code: Alles auswählen

def print_table(filename,delimiter):
    data_lines=[]
    result=""
    with open(filename) as data_file:
        data_lines=data_file.readlines()
        for line in data_lines[:-1]:
            x, y, z=line.strip('\n').split(delimiter)
            result += "['"+x+"', "+y+", "+z+"],\n"
        else:
            x, y, z=data_lines[-1].strip('\n').split(delimiter)
            result += "['"+x+"', "+y+", "+z+"]"

    return result

Als zusätzliche Frage die auch in etwa in diesen Bereich geht noch die Frage:
Wie kann ich z.B. nur jede 5te Zeile einlesen? (Um so eine Grafik mit großerem Zeitfenster zu erhalten)
BlackJack

@FFly82: Die Funktion mag zwar funktionieren, enthält aber einiges sehr unschönes.

Der Name ist falsch denn die Funktion gibt nichts aus sondern erstellt eine Zeichenkette.

Die erste Zuweisung an `data_lines` ist überflüssig weil der Wert niemals irgendwo verwendet wird.

Das wiederholte Zusammensetzen/Erweitern einer Zeichenkette in einer Schleife ist ineffizient weil Zeichenketten unveränderbar sind, dabei also immer neue Zeichenketten erstellt werden in die die bisherigen und die neuen Daten kopiert werden müssen. Deshalb sammelt man die Teilzeichenketten üblicherweise in einer Liste und setzt die dann am Ende mit der `join()`-Methode auf Zeichenketten zusammen. Damit entfällt dann auch der Sonderfall das man zwischen dem letzten Element und dem Rest einen Unterschied machen muss.

Das ``else`` bei dem ``for`` ist falsch. Der Zweig wird grundsätzlich *immer* ausgeführt, also braucht man da kein ``else`` für, sondern kann das ganz normal nach der Schleife machen.

Zum Schreiben und Lesen von CSV-Dateien gibt es in der Standardbibliothek das `csv`-Modul.

Das Zusammensetzen von Zeichenketten und Werten per ``+`` ist eigentlich eher BASIC als Python. In Python verwendet man dafür die `format()`-Methode auf Zeichenketten.

Zu den Fragen: Gezielt die letzten n Zeilen einer Textdatei zu lesen ist nicht möglich weil die Zeilen nicht gleich lang sind, man also nicht weiss zu welchem Byte-Versatz man gehen müsste um den Anfang der n. Zeile von hinten zu erwischen. Man muss also alle Zeilen lesen und sich nur die letzten n davon merken. Das lässt sich mit einer `collection.deque` und der Angabe einer maximalen Länge lösen.

Jedes 5. Element von einem iterierbaren Objekt kann man mit `itertools.islice()` bekommen.
FFly82
User
Beiträge: 2
Registriert: Freitag 14. November 2014, 18:00

Danke.
Damt hab ich zumindest schonmal nen Anhaltpunkt um den ich mich schlau mache.
BlackJack

Ungetestet:

Code: Alles auswählen

import csv
from collections import deque
from itertools import islice


def load_last_rows(filename, step, count, delimiter=';'):
    with open(filename, 'rb') as csv_file:
        reader = csv.reader(csv_file, delimiter=delimiter)
        return list(deque(islice(reader, 0, None, step), count))
Antworten