Hilfe bei Schreiben auf USB-Stick

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
Tinker232
User
Beiträge: 50
Registriert: Mittwoch 25. Juli 2018, 13:45

Hallo zusammen,

für meinen Datenlogger habe ich ein Programm geschrieben, welches die Daten aus einer Queue in eine CSV-Datei auf einem USB-Stick schreibt.
Nachdem ich nun das ganze etwas ausprobiere fällt mir auf, dass die Dateien erst wirklich auf dem Stick vorhanden sind, wenn ich nach dem Schreibvorgang bzw. wenn die Aufnahme beendet ist, über den Dateiexplorer die Datei öffne (mittels LibreOffice Calc) und wieder schließe.
Danach kann ich den USB aushängen, wieder einstecken und die Datei ist nach wie vor vorhanden. Auch wird sie dann auf meinem Windows-PC dargestellt inklusive Inhalt.

Wenn ich jedoch, nachdem die Aufnahme beendet ist, die Datei nicht öffne und einfach den USB aushänge (also sicher entferne) dann wird die Datei auf meinem Win-Pc entweder gar nicht dargestellt, oder sie hat keinerlei Inhalt.
In meinem Programm hab ich jedoch stets darauf geachtet die datei auch wieder zu schließen (datei.close( ))
Hat jemand eine Idee, woran das liegen kann? Eventuell am USB-Stick? Ich hab schon mehrere ausprobiert. Alle sind mit FAT32 formatiert..

Code: Alles auswählen

def writer_run():
    self.queue_daten_sensoren = queue.Queue(1)
    self.datei_pfad = xxxxx
    self.datei_name = "Filename"
    self.datei = open(self.datei_pfad + self.datei_name, "w", newline = ' ', encoding = 'utf-8')
    writer = csv.writer(self.datei, dialect='excel', delimiter=';')
    writer.writerow(["Datum", "Zeit", "Wert"])
    while not self.stop_aufnahme.isSet():
        if self.queue_daten_sensoren.full is True:
            print("Queue ist voll und wird entleert")
            while self.queue_daten_sensoren.empty() is False:
                writer.writerow(self.queue_daten_sensoren.get())
                self.datei.flush()
            self.datei_size = os.path.getsize(self.datei_pfad + self.datei_name)
            if self.datei_size >= 5000:
                self.datei.close()
                return self.writer_run()
    else:
        print("Queue wird zwangsentleert")
        while self.queue_daten_sensoren.empty() is False:
            writer.writerow(self.queue_daten_sensoren.get())
            self.datei.flush()
        self.datei.close()
** EDIT **
Mir ist aufgefallen, dass es an der Aufnahmezeit liegt. Ich habe für die Testversuche immer nur 10 Sekunden aufgenommen. Nachdem ich den USB-Stick sauber ausgeworfen hatte wurde keine mir auf dem Win-Rechner keine Dateien angezeigt. Sobald ich etwas länger aufgenommen hatte werden die Daten auch ganz normal auf dem Windows-PC dargestellt.

Also folgende Fälle sind zu betrachten:

- kurze Aufnahmen ca.10s -> Öffne USB-Stick auf dem RPI -> Datei vorhanden - > Öffnen der Datei -> Inhalt vorhanden -> USB sicher entfernen > Öffne USB-Stick auf dem Win-Rechner -> Datei vorhanden, jedoch kein Inhalt!
- kurze Aufnahmen ca. 10s -> Ohne USB-Sticks auf dem RPI -> Datei vorhanden, aber ohne zu öffnen -> USB Stick sicher entfernen -> Öffne USB-Stick auf dem Win-Rechner -> keine Datei vorhanden! -> anschließend wieder USB-Stick in den RPI -> Öffnen USB-Stick auf dem RPI -> keine Datei vorhanden?

???
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Erstmal eine kurze Anmerkung: statt open/close so wie du es hier zeigst benutzt man genau aus Gruenden der Verlaesslichkeit fuer Dateioperationen nach Moeglichkeit das with-Statement. Und bei dir waere das sehr gut moeglich, da alles in einem Funktionskoerper passiert.

Code: Alles auswählen

with open(...) as datei:
      .... # mach was  mit datei, und auch wenn das Programm abbricht, wird sie geschlossen
Des weiteren ist dein alles an self.-Gebinde ueberfluessig. self.datei wird nur in writer_run benutzt, also sollte das auch keine unnoetige Instanz-Variable sein.

Mit is True solltest du NIEMALS arbeiten. Es gibt keine Garantie, dass das funktioniert. Es reicht in diesem Fall ein einfaches "if bedingung", der zusaetzliche Vergleich mit True ist unnoetig. Wenn du darauf bestehst, dann benutzt ==. Das is funktioniert ist kein zugesichertes Feature des Interpreters.

Und nun nach langer Diskussion was zu deinem eigentlichen Thema: Bist du sicher, dass du dein Programm sauber beendest, und die Datei sauber geschlossen wird? Der Code sieht ziehlich unuebersichtlich aus, und was zB riesen Mist ist, ist dieses mehrfache geschliesse (siehe oben) und der rekursive?!?! aufruf? Mit with wuerdest du auch bei einem return IMMER schliessen, aber so oder so klingt das danach, dass du da deine Logik verbessern musst.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

`self` kommt aus dem nichts, das sollte bei Funktionen nicht der Fall sein. `self` ist auch ein komischer Variablennamen, denn der ist für die Instanz bei Methoden reserviert. Dateipfade setzt man mit os.path.join zusammen. `writer_run` ist bestimmt der falsche Ort, um eine Queue anzulegen, denn die sollte ja dort angelegt werden, wo sowohl der Konsument als auch der Produzent erzeugt wird. Eine Queue-Länge von 1 ist höchstwahrscheinlich etwas kurz.

Queue.full ist eine Methode, also niemals True. Statt explizit auf `empty` zu prüfen würde man ein nicht-blockierendes `get` verwenden. Das Flushen nach jedem writerow ist auch übertrieben. Ein else-Block in einem while ohne break ist unsinnig, weil er immer durchlaufen wird.
Rekursion ist keine Mittel um etwas zu wiederholen. Das sollte man mit einer Schleife lösen. Hier auch ein eigenes Dateiobjekt, das sich ab einer bestimmten Größe selbst spaltet. Doppelten Code in Funktionen auslagern.

Auch ein close ist keine Garantie, dass das Betriebssystem Daten auf den Datenträger schreibt. Ich denke, hier ist irgendetwas am "sicheren entfernen" kaputt.
Tinker232
User
Beiträge: 50
Registriert: Mittwoch 25. Juli 2018, 13:45

Hallo zusammen, ich habe nun das Problem lösen können. Woran es genau lag ist weiß ich nicht. Ich hab jedoch einfach den USB-Stick nochmals auf dem RPI formatiert und auch komplett neu eingehängt.
Jetzt funktioniert es problemlos. Allerdings funktioniert nun der umount Button auf meinem GUI nicht mehr, weshalb ich nach einer Alternative für os.system sudo umount <mount-Point> suche... dazu habe ich bereits einen neuen Thread eröffnet. Liebe Grüße
Antworten