Kyvi - Textdatei auslesen

  • ich benutze kivy in Verbindung mit python und stoße mal wieder an meine Python-Grenzen.


    folgender Code funktioniert, die Funktion "updateText" wird jede Sekunde aufgerufen und liest die Text Datei aus. Wenn nun ein anderes Script die Text Datei gerade bearbeitet (passiert unregelmäßig) , kann die Funktion auf die txt Datei nicht zugreifen und die Liste bleibt leer. Da ich anschließend auf bestimmte Stellen der Liste zugreifen möchte, laufe ich in ein "List index out of range" error

    Code
    1. variable1 = StringProperty()
    2. variable2 = StringProperty()
    3. def updateText(self, dt):
    4. with open("/home/pi/test.txt", "r") as f:
    5. line_list = f.read().splitlines()
    6. self.variable1 = line_list[0]
    7. self.variable2 = line_list[2]

    ich habe es schon hinbekommen, dass lesen in eine eigene Funktion auszulagern und der error abzufangen mit einem except. Ich komme allerdings nicht auf die Logik, wie in dem Moment wenn die Exception mal eintritt einfach die alte liste benutzt wird.

    Kann mir jemand eventuell dort einen Hinweis geben, womit man es realisieren könnte?


    Gruß und voraus schon vielen Dank

  • dbv

    Changed the title of the thread from “Kyvi - Testdatei auslesen” to “Kyvi - Textdatei auslesen”.
  • Hallo,


    `list` ist ein ganz schlechter Name für einen Variable, weil du damit die Build-In Funktion `list`überschreibst. Was zu "lustigen" Nebeneffekten führen kann.


    Bzgl. der Logik: Wenn ein Fehler auftritt führst du einfach `updateText`nicht aus. BTW: Funktionsnamen werden klein_mit_unterstrich geschreiben.


    Also vom Prinzip:

    Python
    1. def _update_text(...):
    2. #do something
    3. def read_text(...):
    4. try:
    5. #einlesen
    6. except IndexError:
    7. pass
    8. else:
    9. _update_text(neuer_text)

    Gruß, noisefloor

  • 1) Gibt es wirklich einen IndexError beim Lesen des Files??

    soweit ich das als Laie sagen kann, ja. ich bekomme einen List index out of range und als Zeile wird mir:

    Code
    1. self.variable1 = line_list[0]

    genannt. Wenn ich es richtig mutmaße, kann er die Datei nicht lesen wenn die Datei gerade geöffnet wird. Bzw. die Liste mit dem Inhalt bleibt halt leer. Da der nachfolgende code auf bestimmte Stellen der Liste zugreift, folgt der index error.



    2) try .. except gehoert in update_text

    ich habe das mal soweit umgeschrieben. Wie kann ich nun in der exception die alte Liste benutzen ?

  • die variablen heißen bei mir alle anders. Ich wollte hier für euch selbst erklärende variablen nutzen, damit da nicht 10mal nachgefragt werden muss.


    wenn ich deinen code richtig verstehe muss ich nun read_text() regelmäßig ausführen?

  • Hallo,


    Quote

    wenn ich deinen code richtig verstehe muss ich nun read_text() regelmäßig ausführen?

    Richtig, und read_text für _update_text aus. _updatr_text muss ja nicht aufgerufen werden, wenn read_text kein Ergebnis hat.


    Quote

    Ich wollte hier für euch selbst erklärende variablen nutzen,

    Äh... du solltest in erster Linie für DICH (!) selbsterklärende Variablen nutzen. Du hast den größten Nutzen davon, nicht wir.


    Gruß, noisefloor

  • Richtig, und read_text für _update_text aus. _updatr_text muss ja nicht aufgerufen werden, wenn read_text kein Ergebnis hat.

    ich habe es nun mal so umgesetzt

    leider laufe ich hier in den gleichen error. den index error bekommt er erst in "_update_Text", da er dort in der 2ten Zeile erst merkt, dass die Liste leer ist.



    Äh... du solltest in erster Linie für DICH (!) selbsterklärende Variablen nutzen. Du hast den größten Nutzen davon, nicht wir.


    Gruß, noisefloor

    ich überarbeite die variablen am Ende, danke ! :)

  • Hallo,


    Quote

    leider laufe ich hier in den gleichen error. den index error bekommt er erst in "_update_Text", da er dort in der 2ten Zeile erst merkt, dass die Liste leer ist.

    Ach stimmt - Denkefehler meinerseits. Dann müsstest du z.B. nach dem Lesen und vor dem Aufruf _update_text z.B. die Länge der Liste prüfen.


    Gruß, noisefloor

  • Hallo,


    Ach stimmt - Denkefehler meinerseits. Dann müsstest du z.B. nach dem Lesen und vor dem Aufruf _update_text z.B. die Länge der Liste prüfen.


    Gruß, noisefloor

    das sollte des Rätsels Lösung sein. Ich beobachte das mal ein paar Stunden und melde mich dann nochmal.


    EDIT:

    Code
    1. File "main.py", line 99, in read_txt
    2. self.update_Text(list_old)
    3. UnboundLocalError: local variable 'list_old' referenced before assignment

    leider nein...


    Gruß

    Edited once, last by Danjin ().

  • Hallo,


    dann denk' mal scharf drüber nach, ob du list_old überhaupt brauchst... Und wenn du dann richtigerweise zu dem Ergebnis gekommen bist, dass das es nicht brauchst, überdenkst du nochmal den Code im `else` Block, der zu `try` gehört.


    Wenn die Datei `test.txt` existiert - egal ob leer oder nicht - , dann wird der `try` Block immer durchlaufen und nie eine Exception werfen.


    Nackte try...except sind fast immer falsch, weil du damit _alle_ Fehler, inkl. Programmierfehler abfängst. Willst du aber nicht.


    Zeile 7 im Code aus Post #9 ist überflüssig, weil du damit die Variablen nur zusätzlich an einen weiteren Namen bindest.


    Welchen Sinn hat das `return` Statement der Funktion `read_txt`?


    Tipp: Programmieren ist nicht raten und Programmieren ist nicht Copy & Paste. Denk' mal _in_Ruhe_ über den Ablauf dieses Programmteils nach, male ihn dir auf ein Blatt Papier inkl. aller gewünschten bzw. möglichen Verzweigungen und dann schreibst du den Code neu.


    Gruß, noisefloor

  • dann denk' mal scharf drüber nach, ob du list_old überhaupt brauchst... Und wenn du dann richtigerweise zu dem Ergebnis gekommen bist, dass das es nicht brauchst,

    Doch, list_old bzw. mittlerweile list_backup brauche ich unbedingt und das war quasi auch genau das, wonach ich hier fragte. Wenn die Datei nicht gelesen werden kann, ist die Liste leer --> list []. Da ich in meinem code aber auf bestimmte Stelle der Liste zugreife und dies bekanntlich mit einer leeren Listenicht geht, muss in diesem Szenario eine "1sekunde" veraltete Liste benutzt werden.

    Wenn die Datei `test.txt` existiert - egal ob leer oder nicht - , dann wird der `try` Block immer durchlaufen und nie eine Exception werfen.


    Nackte try...except sind fast immer falsch, weil du damit _alle_ Fehler, inkl. Programmierfehler abfängst. Willst du aber nicht.

    habe ich soweit entfernt.


    Welchen Sinn hat das `return` Statement der Funktion `read_txt`?

    das return muss natürlich in _update_Text damit ich die back_up liste aktualisieren kann.

    ich habe das Problem nun soweit gelöst und es funktioniert alles wie ich möchte. habe den code mal hinzugefügt, für leute die das gleiche machen wollen oder die es einfach interessiert

  • Hallo,


    Quote

    Doch, list_old bzw. mittlerweile list_backup brauche ich unbedingt und das war quasi auch genau das, wonach ich hier fragte. Wenn die Datei nicht gelesen werden kann, ist die Liste leer --> list [].

    Nein, brauchst du _nicht_. Du hast lediglich einen konzeptionellen Denkfehler. Wenn die gelesene Liste leer ist, dann überschreibst du die bestehende Liste halt _nicht_. Dann sparst du dir auch die Krücke via old_list oder was auch immer.

    Und wenn die Liste leer ist, dann rufst du halt _nicht_ update_text auf.

    Du solltest hier nochmal die Aufteilung von deinem Code überdenken und das ggf. auf mehr Funktionen aufteilen.


    Mal abgesehen davon kennen wir deinen restlichen Code nicht. Und auf Basis des gezeigten Codes kann keiner Wissen, ob du ggf. die Liste noch woanders brauchst. So was musst du dann schon explizit von Anfang an sagen.


    Der Code Post #11 ist ein bisschen schräg. Zeile 3 ist schräg - wozu ist das, eine Liste mit leeren Strings? Wenn du Platzhalter brauchst, nimm' `None`. Zeile 4 ist schräg - `__init__` ohne Klasse? Zeile 15 ist schräg. Ja, das geht, aber Listen kennen eine Methode `clear`, das ist schöner. Die Frage ist auch, warum du die Liste nicht direkt leer anlegst. Weil: im gezeigten Code wir die Default Liste nie benutzt, sondern wenn nur geleert.


    Ansonsten ignorierst du scheinbar geflissentlich, was ich dir zu Variablennamen geschrieben habe. Wenn du früher oder später scheinbar nicht nachvollziehbare Fehler bekommst, denk' einfach nochmal an das, was ich dir in Post #3 geschrieben habe.


    Gruß, noisefloor

  • Nein, brauchst du _nicht_. Du hast lediglich einen konzeptionellen Denkfehler. Wenn die gelesene Liste leer ist, dann überschreibst du die bestehende Liste halt _nicht_. Dann sparst du dir auch die Krücke via old_list oder was auch immer.

    Und wenn die Liste leer ist, dann rufst du halt _nicht_ update_text auf.

    Du solltest hier nochmal die Aufteilung von deinem Code überdenken und das ggf. auf mehr Funktionen aufteilen.

    tatsächlich. Da habe ich einen Denkfehler gehabt und zu sehr meinen altes Codekonstrukt im Kopf gehabt. Danke! sparrt mir einiges an codezeilen :)

    deine Kritik zu Zeile 3 und 15 hat sich damit auch erledigt, weil ich das alles nicht mehr brauche.

    Zeile 4 ist schräg - `__init__` ohne Klasse?

    ich besitze davor eine Klasse.


    Die Frage ist auch, warum du die Liste nicht direkt leer anlegst. Weil: im gezeigten Code wir die Default Liste nie benutzt, sondern wenn nur geleert.

    ich hatte die Struktur so gewählt, weil wenn er gleich am Anfang in den Error läuft, noch keine back_up liste hatte.


    Ansonsten ignorierst du scheinbar geflissentlich, was ich dir zu Variablennamen geschrieben habe. Wenn du früher oder später scheinbar nicht nachvollziehbare Fehler bekommst, denk' einfach nochmal an das, was ich dir in Post #3 geschrieben habe.

    ich ignoriere es nicht. Den Hinweis habe ich dankend angenommen und kümmere mich am Ende (also jetzt) drum :)


    hier mein code

  • Hallo,


    sieht doch besser aus :-) Im gezeigten Code hat Zeile 10 `return data` keinen Sinn, weil im Aufruf (Zeile 15) kein Rückgabewert erwartet wird. Außerdem liefert die Funktion so wie so nur das zurück, was rein gegeben wurde.


    Gruß, noisefloor