ConfigParser - INI File schreiben

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
Benutzeravatar
Muntliger
User
Beiträge: 40
Registriert: Montag 19. November 2018, 09:09

Hallo,

ich bin ein Python-Neuling aus Österreich.
Momentan bin ich beschäftigt mit dem Erstellen eines Scripts zum lesen/auswerten/speichern von Sensordaten/S0-Eingängen.
Dies läuft auch schon super bis auf folgendes Problem:

Das Gerät (ein OnionOmega2+) wird über 24V versorgt.
Wenn diese Spannung aus irgendeinem Grund wegfällt und das Modul ConfigParser gerade am Schreiben eines INI Files war – ist das file nach dem Neustarten leer und das Python Script startet nicht mehr.

Hat jemand eine Lösung wie ich dieses Problem umgehen kann?

Im INI File stehen einige Daten wie – Kanalnamen/Reboot Anforderung usw.
Das INI File kann über eine Website geändert werden – damit die Daten die das Script benötigt angepasst werden können.

Vielen Dank im Voraus.
Daniel
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Du könntest vor jedem Schreibzugriff eine Sicherheitskopie anlegen. Dann hättest du nach einem solchen Vorfall zumindest noch die alte Version zur Hand...
Benutzeravatar
Muntliger
User
Beiträge: 40
Registriert: Montag 19. November 2018, 09:09

stimmt - könnte dann auch automatisch checken ob das file leer ist und die sicherheitskopie verwenden - falls leer.
__deets__
User
Beiträge: 14533
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist ein ziemlich komplexes Thema, das du nicht mal so eben selbst geloest bekommst.

https://courses.cs.washington.edu/cours ... osdi14.pdf

Eine gute herangehensweise ist die Verwendung von sqlite (https://news.ycombinator.com/item?id=11511422) weil das schon viele der Mechanismen eingebaut hat, die du dir sonst muehselig von Hand erarbeiten musst.
__deets__
User
Beiträge: 14533
Registriert: Mittwoch 14. Oktober 2015, 14:29

snafu hat geschrieben: Montag 19. November 2018, 09:57 Du könntest vor jedem Schreibzugriff eine Sicherheitskopie anlegen. Dann hättest du nach einem solchen Vorfall zumindest noch die alte Version zur Hand...
Statt eine Kopie anzulegen (also eine NEUE Datei, die ggf. noch nicht gespeichert wurde wenn das System kracht) und dann die alte Datei zu modifizieren (die dann ebenfalls unbekannten Zustand hat), macht man das ueblicherweise so:

- neue Datei mit neuen Werten anlegen, die einen temporaeren Namen hat.
- alte Datei umbennen, zb zu config.ini.old. Das ist eine kuerzere, "sicherere" Operation, die den eigentlichen Inhalt nicht anfasst.
- neue Datei zum Namen der alten umbenennen.
- Daumen druecken.

Siehe meinen anderen Post, was da noch besser ist.
Benutzeravatar
Muntliger
User
Beiträge: 40
Registriert: Montag 19. November 2018, 09:09

Für mich sieht die Lösung mit der Sicherheitskopie sicherer aus, aber evtl. täusche ich mich auch.

1. config.ini.new - schreiben
2. config.ini zu config.ini.old "verschieben"
3. config.ini.new zu config.ini "verschieben"

Wenn ich nun einen Absturz zwischen 2-3 habe, habe ich kein ini file mehr.



Lösung 1
1. config.ini zu config.ini.old "kopieren"
2. config.ini mit neuen werten überschreiben

ich checke nun bei jedem start ob die config.ini ok ist - wenn nicht kopiere ich config.ini.old zu config.ini


Villeicht muss ich mir wirklich überlegen ob ich das mit sqlite mache - obwohl die INI files ansonsten doch ziemlich fein zu handhaben sind.
__deets__
User
Beiträge: 14533
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du hast den Artikel offensichtlich nicht gelesen, den ich verlinkt habe. Das Problem ist, dass (wie ich ja auch schon schrieb) in deinem Schritt 1 Daten im FS-Cache des Systems landen. Das tun dann auch in Schritt 2 welche. Wenn dann also ein Absturz kommt, sind beide Dateien kaputt. Das umbenenne ist eine kleinere, und "sicherer" Operation. Ja, davon hast du zwei, aber die sind eben klein und atomar (leider nicht so atomar wie man sich das wuenschen wuerde). Darum ist mein Vorgehen vorzuziehen. Noch besser eben sqlite, weil die sich viel Muehe gemacht haben, solche Operationen sicher zu gestalten. Eine 100%ige Sicherheit gibt es natuerlich nicht, dazu waere es besser, mit Hardware im Sinne zB einer USV obendrauf zu arbeiten, um ein gesichertes herunterfahren zu gewaehrleisten.
Sirius3
User
Beiträge: 17745
Registriert: Sonntag 21. Oktober 2012, 17:20

Wenn man die keine Sicherungskopie braucht, garantiert folgende Lösung, dass immer ein korrektes ini-File abliegt (wenn man ein System benutzt, das eine chronologische Schreibreihenfolge garantiert):

1. schreibe config.ini.neu
2. umbenennen config.ini.neu -> config.ini
Benutzeravatar
Muntliger
User
Beiträge: 40
Registriert: Montag 19. November 2018, 09:09

@__deets - den Artikel hab ich mir noch nicht durchgelesen - sorry.
das sqlite3 Modul von pyhton hab ich mir gerade angeschaut/getestet - funktioniert super

@Sirius3 - ich hab gedacht das modul ConfigParser macht das intern - muss ich mir nochmal genauer anschauen.
__deets__
User
Beiträge: 14533
Registriert: Mittwoch 14. Oktober 2015, 14:29

Sirius3 hat geschrieben: Montag 19. November 2018, 14:20 Wenn man die keine Sicherungskopie braucht, garantiert folgende Lösung, dass immer ein korrektes ini-File abliegt (wenn man ein System benutzt, das eine chronologische Schreibreihenfolge garantiert):

1. schreibe config.ini.neu
2. umbenennen config.ini.neu -> config.ini
Schritt 2 schlägt fehl, da du erst die Alte umbenennen musst.

Edit: ich habe as gerade nochmal ausprobiert, und es geht tatsaechlich doch. I stand corrected. Womit das natuerlich nochmals eine Verbesserung darstellt. Ich bin mir aber ziemlich sicher das mir das mal irgendwo um die Ohren geflogen ist. Darum wundere ich mich, dass es jetzt geht. Vielleicht war das unter Windows, und der Code musste auf beiden Plattformen funktionieren.
Benutzeravatar
Muntliger
User
Beiträge: 40
Registriert: Montag 19. November 2018, 09:09

Funktioniert super auf meinem System - ist ein Onion Omega 2 mit OpenWRT OS.

Hab nun die ganze Nacht im ~5min Takt ein/ausschalten lassen - funktioniert immer noch.
Davor hatte ich nach dem 5-6 Neustart immer die Probleme.

Vielen Dank für eure Hilfe - hatte selten so ein Hilfsbereites und "schnelles" Forum.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1019
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Schonmal darüber nachgedacht?

Code: Alles auswählen

Signature: configparser.ConfigParser.read(self, filenames, encoding=None)
Docstring:
Read and parse a filename or an iterable of filenames.

Files that cannot be opened are silently ignored; this is
designed so that you can specify an iterable of potential
configuration file locations (e.g. current directory, user's
home directory, systemwide directory), and all existing
configuration files in the iterable will be read.  A single
filename may also be given.

Return list of successfully read files.
File:      ~/.pyenv/versions/3.7.1/lib/python3.7/configparser.py
Type:      function
Du machst einfach eine default-config, um die Funktion zu gewährleisten. Die wird auch nicht verändert.
Die andere Benutzer-Config wird dann als zweites geladen und überschreibt die Werte von der ersten.
Fehler beim Lesen werden mit Absicht ignoriert, das sollte man auf jeden Fall wissen, wenn man diese Funktion anwendet.

Könnte dann so aussehen:

Code: Alles auswählen

cfg = configparser.ConfigParser()
cfg.read(['cfg1.ini', 'cfg2.ini'])
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Antworten