Textdatei 'sicher' beschreiben

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
Karl
User
Beiträge: 252
Registriert: Freitag 29. Juni 2007, 17:49

Hallo, ich schreibe gerade ein Skript, das basierend auf der Usereingabe mehrere hundert Zeilen in eine Textdatei schreiben wird. Für jede Zeile ist eine Usereingabe notwendig.
Es wäre also sehr blöd, wenn das Skript aus welchem Grund auch immer, an irgendeiner Stelle irgendeinen Fehler bekommt, der PC abstürzt, oder dergleichen - und der ganze Fortschritt weg wäre.

Wie würdet ihr vorgehen, um nach jedem Eintrag den Fortschritt zu sichern, sodass es praktisch ausgeschlossen ist, dass so ein Fall einreten kann? Sind die write-Operationen schon von Haus aus robust genug oder reicht es bereits, die Datei nach jedem Eintrag neu zu öffnen und zu schließen?
Benutzeravatar
CrisBee
User
Beiträge: 61
Registriert: Mittwoch 2. Oktober 2013, 10:45
Wohnort: Bielefeld
Kontaktdaten:

Wenn mich nicht alles täuscht, dann kannst du die Textdatei im Append Mode öffnen 'a+', damit wird der String immer hinten angehängt. Das Ganze realisierst du in einer Schleife, so dass nach jeder Eintragung die Datei wieder geschlossen wird.

Aber ich bin selber Neuling, also vielleicht hat ein User mit mehr Erfahrung einen besseren Vorschlag.
Das Reallife ist nur etwas für Leute, die keine Freunde im Internet haben! :P
Meine Fotografie: http://www.cutefeet.de
BlackJack

@Karl: Das reicht nicht, weil das Betriebssystem trotzdem erst einmal alles im RAM zwischenspeichern kann. Schau Dir mal `os.fdatasync()` an. Das mit schliessen und öffnen der Datei zwischen jedem Schreibvorgang macht keinen Sinn.
Benutzeravatar
CrisBee
User
Beiträge: 61
Registriert: Mittwoch 2. Oktober 2013, 10:45
Wohnort: Bielefeld
Kontaktdaten:

Danke BlackJack! :mrgreen:
Das Reallife ist nur etwas für Leute, die keine Freunde im Internet haben! :P
Meine Fotografie: http://www.cutefeet.de
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Aus Usabilitysicht hört sich das aber auch alles andere als toll an... wenn ich mehrere Hundert Eingaben mache, dann will ich das doch beliebig unterbrechen können‽

Letztlich stelle ich mir das vor, wie bei jedem anderen Programm auch, mit welchem man umfangreiche Eingaben macht. Sei es nun ein Texteditor oder ein CAD Programm oder sonst was. Der Benutzer muss eben ab und an speichern bzw. das Programm sichert alle paar Minuten mal Arbeit weg. Ansonsten ist eben die Arbeit von zwischendurch verloren.

Abstürze usw. sind ja schön und gut, aber was ist denn mit dieser imho Standard Anforderung?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

Es klingt auch ein wenig paranoid, denn kein normales Programm macht das. Texteditoren, Tabellenkalkulationen, CAD-Programme usw. speichern alle einfach nur, ohne sich speziell darum zu kümmern ob die Daten nun wirklich *sofort* auf dem Hintergrundspeicher ankommen. So ein erzwungenes Syncen bremst nämlich auch das System aus. Wann was wohin gespeichert wird, kann das Betriebssystem auf einem Mehrprozess-System nämlich in der Regel effizienter koordinieren als einzelne Anwendungsentwickler. Explizites Syncen beschränkt sich in der Regel auf so etwas wie systemrelevante Logdateien wo man nach einem Absturz die kurz vor dem Absturz geschriebenen Daten brauchen kann um die Ursache für den Absturz zu analysieren.
Karl
User
Beiträge: 252
Registriert: Freitag 29. Juni 2007, 17:49

Aus Usabilitysicht hört sich das aber auch alles andere als toll an... wenn ich mehrere Hundert Eingaben mache, dann will ich das doch beliebig unterbrechen können‽
Äh, deshalb will ich ja gerade, dass nach jedem Eintrag gespeichert wird, was genau meine Frage ist? :) Unterbrechen können soll man das jederzeit entweder per Script schließen, oder eine entsprechende Konsoleneingabe.
Da ich das Programm erst mal sowieso nur für meine privaten Zwecke nutze, muss es nicht allzu viel Usability haben, sondern vorranging das tun, was ich will.

@BlackJack: Performance sollte wirklich kein Problem sein, wenn man alle paar Sekunden eine Zeile in eine Textdatei schreibt. Ich glaube ich könnte die Datei zwischendurch millionenfach öffnen und schließen.

Wenn die Quintessenz jetzt aber ist, dass normales Beschreiben (also file.write()) auch reicht, bin ich damit auch zufrieden. Wollte nur unangenehmen Überraschungen vorbeugen :)
BlackJack

@Karl: Doch Performance ist ein Problem beim erzwungenen Syncen, was auch nichts mit öffnen und schliessen von Dateien zu tun hat. Ständiges öffnen und schliessen hat nur einen Effekt auf das Programm welches das tut. Mit einem Sync bremst man andere Programme im Plattenzugriff aus und blockiert das Programm das den Sync angefordert hat solange bis der durch ist. Das Betriebssystem regelt das besser als Anwendungsprogrammierer die denken ihr Programm wäre das wichtigste und braucht unbedingt Vorfahrt, weil das Betriebssystem einen Überblick über alle anstehenden Lese- und Schreibvorgänge hat, und die versucht in einer möglichst günstigen Reihenfolge abzuarbeiten, so dass das Gesamtssystem flüssig läuft.

Ein Absturz wenn man gerade mitten am arbeiten ist, ist immer eine unangenehme Überraschung, aber doch auch äusserst selten. Falls das nicht selten ist, sollte man die Ursache finden und beseitigen, und nicht einzelne Programme ”sicherer” machen. Da hat man mehr von.
Karl
User
Beiträge: 252
Registriert: Freitag 29. Juni 2007, 17:49

Deine ideologischen Vorstellungen haben durchaus ihre Berechtigung und grundsätzlich stimme ich dir auch vollkommen zu.
Aber hier handelt es sich wirklich um en Szenario, in dem selbst mein Taschenrechner noch unterfordert wäre, also denke ich, dass man das nicht so eng sehen muss. Aber streiten wir uns nicht, für mich ist die Sache jetzt klar, danke :)
BlackJack

@Karl: Ich weiss jetzt nicht was Du mit „idiologisch” meinst!? Das Betriebssystem hat den Überblick über die anstehenden Lese- und Schreiboperationen und wo die auf der Platte stattfinden, und welche Programme am längsten schon keine Daten mehr bekommen haben oder losgeworden sind, und versucht die alle möglichst effizient zu bedienen. Datentransfer von und zur Platte und unnötige Kopfbewegungen dauern Grössenordnungen länger als Datentransfers zwischen Prozessor und RAM und Verarbeitung der Daten in der CPU. Und da pfuscht ein Sync dazwischen und zwar anscheinend in Deinem Fall regelmässig. Und dem gegenüber steht ein ”Gewinn” der fast 0 ist. Das ist einfach unsinnig. Wenn das mehr Leute für nicht so schlimm halten würden und so etwas in ihre Programme einbauen, zwingt das auch sehr leistungsstarke Rechner in die Knie.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Karl hat geschrieben:
Aus Usabilitysicht hört sich das aber auch alles andere als toll an... wenn ich mehrere Hundert Eingaben mache, dann will ich das doch beliebig unterbrechen können‽
Äh, deshalb will ich ja gerade, dass nach jedem Eintrag gespeichert wird, was genau meine Frage ist? :)
Und wieso muss dann nach *jedem* Eintrag gespeichert werden? Wenn man die Eingabe nach dem Speichern an einer *beliebigen* Stelle wieder aufnehmen kann, braucht es doch so etwas nicht‽

In meinem Texteditor kann ich nach jeder Zeile speichern oder eben erst nach 10 oder gar 20 Zeilen oder zum Teufel auch erst, wenn ich 1000 Zeilen Code geschrieben habe. Da bleibt es mir als Anwender überlassen, wie viele Änderungen ich am Stück mache. Wer aufgrund eines Absturzes viele Stunden Arbeit verliert, der wird in Zukunft eben häufiger speichern - aber sicherlich nicht nach jeder Zeile / Eintrag.

Also dieses Szenario würd ich ja doch gerne mal kennen lernen, was das rechtfertigt. Zumal es sich um die Einträge in eine Textdatei handelt :!: Dafür sind die Dinger imho nicht ausgelegt. Bei solch einer Anforderung müsstest Du die Einträge imho an irgend einen Dienst schicken, der die verwaltet, etwa eine Datenbank in jedweder Form o.ä.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Nocta
User
Beiträge: 290
Registriert: Freitag 22. Juni 2007, 14:13

Erst mal will ich noch mal betonen, dass es sich um ein Skript handelt, das für mich persönlich etwas erledigen soll.
Was es macht, ist nach einer Usereingabe eine Zeile in eine Textdatei zu schreiben. Das wird dann alle paar Sekunden gemacht, je nachdem wie schnell ich bin.

Meine Frage bezog sich ursprünglich nur darauf, ob ich zusätzliche Maßnahmen ergreifen sollte, um das Datei-schreiben abzusichern. Ich könnte durchaus mal eine Stunde lang tippen und wenn dann alles weg wäre, wäre das sehr ärgerlich.
Mir ist durchaus bewusst, wie der Computer in seinen Grundzügen arbeitet und wie das Betriebssystem die Prozesse verwaltet. Aber die ganz spezielle Frage, ob ich bei file.write() Vorkehrungen treffen sollte, um den Fortschritt zu speichern, war/ist mir nicht ganz klar, weil ich schlicht und einfach nicht exakt weiß, wie diese Methode und das Betriebssystem usw sich verhalten.
BlackJack hat geschrieben:ch weiss jetzt nicht was Du mit „idiologisch” meinst!?
Damit meine ich, dass deine Ansichten das wiederspiegeln, was man bei einem guten Design machen sollte. Ideologisch, weil es zwar gut und richtig so ist, aber nicht in jedem Fall dem praktisch gegangenem Weg entsprechen dürfte.
BlackJack hat geschrieben:Wenn das mehr Leute für nicht so schlimm halten würden und so etwas in ihre Programme einbauen, zwingt das auch sehr leistungsstarke Rechner in die Knie.
Natürlich, ist ja auch klar. Aber gucken wie uns doch mal die Verhältnismäßigkeit an: SSD, moderne CPU, PC macht sowieso nicht viel, wenn ich dieses Skript benutze - Performance? Mir doch egal, von mir aus kann das Ding zwischen meinen Usereingaben noch ein paar Graphenisomorphien nachrechnen.



@Hyperion: Schön, dass du so einen tollen Texteditor hast, aber der hat sicherlich mehr als 50-100 Zeilen und eine Entstehungsgeschichte von mehr als 20 Minuten, oder?
Das hier ist ein simples "Quick'n Dirty" Skript, welches mir in meinem Alltag grad mal etwas erleichtern soll. Es soll auch nicht noch irgendwelche generischen Aufgaben erfüllen, oder Schnittstellen für Erweiterungen und ein gutes OO-Design haben. Es soll einfach das machen, was ich will, und zwar genau das und nichts anderes. Und das ist nicht gerade sehr viel.



Ich will nicht falsch verstanden werden: Ich finde dieses Forum sehr toll und auch gerade die tollen und oft hilfreichen Beiträge von Blackjack sind immer sehr beliebt bei mir, wenn ich mal im Forum stöbere.
Aber irgendwie ist jetzt aus einer Mücke ein Elefant geworden. Ich will einfach, dass mein Skript tut und möglichst auch - für welchen Fall auch immer - die Daten nicht verliert.
Da mein Skript eine Textdatei beschreiben soll, lag es mir jetzt nahe, lieber dort eine - vielleicht unschöne - Lösung zu suchen, als mir jetzt noch Gedanken über irgendwelche Dienste/Datenbanken zu machen.

Ob und wie viele unnötige CPU-Zyklen und Speicherzugriffe ich mir damit einhandle, ist da doch vollkommen egal. Aber hier werde ich irgendwie direkt für den Vorschlag verteufelt, ein paar unnötige Festplattenzugriffe zu verursachen (auf meinem System, auf dem eh nichts passiert).


Wenn ich jemals für ein breiteres Publikum als mich selbst entwicklen sollte, dann würde ich jedem eurer Worte bedingungslos zustimmen. Wenn ich etwas entwickle, das auch gleichzeitig Spaß beim Programmieren machen soll, würde ich auch nie so programmieren.
Ich hoffe, ihr nehmt mir diese gottlosen Blasphemien nicht zu sehr übel :)
BlackJack

@Nocta: Eben doch, das dürfte in jedem Fall dem praktisch gegangenen Weg entsprechen *nicht* selber den Sync-Vorgang zu erzwingen. Das ist eine Möglichkeit die nur für ganz wenige Spezialfälle interessant ist, und in allen anderen Fällen nichts bringt, aber schadet. Das dieser Schaden bei Dir sehr gering ist, macht es trotzdem zu einer ziemlich unsinnigen Idee das einzubauen. Speichere einfach regelmässig, zum Beispiel nach der Eingabe jeder Zeile, und vertraue darauf dass das Betriebssystem das schon so zeitnah wie es effizient möglich ist, sichern wird. Insbesondere wenn das System sonst so gut wie nichts tut, steht dem doch auch überhaupt nichts entgegen. Arbeit von Stunden kann doch nur verloren gehen wenn das System ständig über diesen Zeitraum einen Prozess hat der ununterbrochen auf die Platte zugreift und eine höhere IO-Priorität hat als Dein Programm, und/oder selber ständig synct.

Das einzige Programm an das ich mich so spontan erinnern kann was so einen Unsinn macht(e?) war der Daemon der die Bitcoin-Wallet auf den neuesten Stand bringt. Der schreibt/synct ständig jedes neue Datenpaket. Praktisches Gegenmittel: `libeatmydata` — eine Shared Library die man per `LD_PRELOAD` laden kann und die `sync()` & Co für einen Prozess durch Nulloperationen ersetzt. Vorher eine Sicherheitskopie von der Wallet-Datei zu machen und dann den Daemon mit dieser Bibliothek zu laden war *wesentlich* schonender für das System und meine Nerven. :-)
Nocta
User
Beiträge: 290
Registriert: Freitag 22. Juni 2007, 14:13

Na gut, ich wusste halt beim Stellen der Frage nicht, ob es sich überhaupt so weit aufschieben kann, dass der Datenverlust relevant wird. Ich hatte mich auch gefragt, ob der vielleicht in manchen Fällen erst beim file.close() überhaupt Daten in die Datei schreibt. (Vielleicht gibt es das ja auch? Na ja, egal)

War ja nur ein Vorschlag und außerdem kann man "alle paar Sekunden bei Usereingabe syncen" wohl schwerlich mit dem von dir genannten Programm vergleichen. Wobei es immerhin eine interessante Anekdote ist :)


PS: Wer sich über den geänderten Account-Namen wundert, tut mir leid für die Verwirrung, hatte mal mein PW vergessen und mich jetzt ausversehen mit dem anderen wieder eingeloggt.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Nocta hat geschrieben:Ob und wie viele unnötige CPU-Zyklen und Speicherzugriffe ich mir damit einhandle, ist da doch vollkommen egal. Aber hier werde ich irgendwie direkt für den Vorschlag verteufelt, ein paar unnötige Festplattenzugriffe zu verursachen (auf meinem System, auf dem eh nichts passiert).+
Woher sollen wir das denn wissen? Bei allgemeinen Fragen muss man nunmal davon ausgehen, dass es ein allgemeines Problem ist. Da es leider genug Anwendungen gibt die einfach nur dämlich programmiert sind muss man in eigenem Interesse auf die Probleme deiner Anforderungen hinweisen. Denn in 99% aller Fälle ist das, was du da willst, eine wirklich bescheuerte Idee. Also bevor du dich angegriffen fühlt: Woher sollen wir denn wissen wofür du das brauchst?
bfm
User
Beiträge: 88
Registriert: Donnerstag 14. März 2013, 09:42

Hallo,

mal so eine Zwischenfrage zum Verständnis: Reicht es nicht aus, die Datei mit "with" zu öffnen? Das wird einem doch immer angeraten, weil hier die geöffnete Datei bei einer Ausnahme im Skript wieder ordnungsgemäß geschlossen wird. Und ich gehe jetzt mal davon aus, dass in einem solchen Fall die Daten, die evtl. noch im Schreibcache oder sonst wo stehen, dann noch vom Interpreter/Betriebssystem auf die Platte geschrieben werden. Oder?

Ich denke mal, zu 98% wird "nur" das Skript mit einer Ausnahme abbrechen. In den wenigstens Fällen wird der Pythoninterpreter absaufen. Und wenn das Betriebssystem dann mal abschmiert, dann ich glaub die kleine verhunzte Textdatei das kleinste Problem.

mfg
BlackJack

@bfm: Selbst ohne ``with`` und bei einem hart abgestürzten Python-Prozess werden normalerweise vom Betriebssystem alle offenen Dateien vom Prozess ordnungsgemäss geschlossen und dabei auch Pufferinhalte rausgeschrieben. Die Datenstrukturen von Dateien, inklusive die Puffer werden ja vom Betriebssystem verwaltet und nicht vom abgestürzten Prozess. Die Pufferinhalte gehen durch einen Prozessabsturz also nicht verloren.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@BlackJack: es ist prinzipiell schon möglich, dass Python selbst nochmal die Daten puffert und die sind bei einem Programmabsturz futsch.
Antworten