Was ist die Pythonic-Methode, um nicht schwerwiegende Fehler in einem Parser zu melden?

8

Ein von mir erstellter Parser liest aufgezeichnete Schachpartien aus einer Datei. Die API wird wie folgt verwendet:

%Vor%

Manchmal werden illegale Züge (oder andere Probleme) angetroffen. Was ist eine gute pythonische Art, mit ihnen umzugehen?

  • Auslösen von Ausnahmen, sobald der Fehler auftritt. Dies führt jedoch dazu, dass jedes Problem fatal ist, da die Ausführung gestoppt wird. Häufig gibt es noch nützliche Daten, die analysiert wurden und zurückgegeben werden könnten. Außerdem können Sie den nächsten Datensatz nicht einfach weiter analysieren, da wir uns immer noch in der Mitte einiger halb gelesener Daten befinden.

  • Akkumulieren Sie Ausnahmen und erhöhen Sie sie am Ende des Spiels. Dies macht den Fehler wieder fatal, aber zumindest können Sie es fangen und das nächste Spiel weiter analysieren.

  • Führen Sie ein optionales Argument wie folgt ein:

    %Vor%

Werden einige dieser oder andere Methoden in freier Wildbahn verwendet?

    
Niklas 14.10.2014, 09:35
quelle

5 Antworten

6

Tatsächlich sind diese fatalen Fehler - zumindest soweit es möglich ist, ein korrektes Spiel zu reproduzieren; auf der anderen Seite, vielleicht hat der Spieler tatsächlich die illegale Bewegung gemacht und niemand hat es bemerkt (was es zu einer Warnung machen würde, nicht zu einem fatalen Fehler).

Angesichts der Möglichkeit, dass sowohl schwerwiegende Fehler (Datei ist beschädigt) und Warnungen (eine illegale Bewegung wurde gemacht, aber nachfolgende Bewegungen zeigen Konsistenz mit dieser Bewegung (mit anderen Worten, Benutzerfehler und niemand fing es zu der Zeit), empfehle ich eine Kombination der ersten und zweiten Optionen:

  • löst eine Ausnahme aus, wenn das fortgesetzte Analysieren keine Option ist
  • sammelt alle Fehler / Warnungen, die das weitere Parsen bis zum Ende nicht ausschließen

Wenn Sie keinen fatalen Fehler bemerken, können Sie das Spiel am Ende mit allen Warnungen / nicht-fatalen Fehlern zurückgeben:

%Vor%

Aber was, wenn Sie einen fatalen Fehler treffen?

Kein Problem: Erstellen Sie eine benutzerdefinierte Ausnahme, an die Sie den verwendbaren Teil des Spiels und alle anderen Warnungen / nicht-fatalen Fehler anfügen können:

%Vor%

Wenn Sie den Fehler abfangen, können Sie mit den Warnungen und Fehlern auf den wiederherstellbaren Teil des Spiels zugreifen.

Der benutzerdefinierte Fehler könnte lauten:

%Vor%

und in Verwendung:

%Vor%

Dies ist ähnlich wie das subprocess Modul Fehler behandelt.

Für die Fähigkeit, nachfolgende Spiele nach einem fatalen Fehler des Spiels abzurufen und zu analysieren, würde ich eine Änderung in Ihrer API vorschlagen:

  • habe einen Spiel-Iterator, der einfach die rohen Daten für jedes Spiel zurückgibt (er muss nur wissen, wie er weiß, wann ein Spiel endet und das nächste beginnt)
  • Lassen Sie den Parser die rohen Spieldaten übernehmen und analysieren Sie ihn (damit er nicht mehr für die Datei verantwortlich ist, in der Sie gerade sind)

Auf diese Weise können Sie immer noch versuchen, die Spiele 3, 4 und 5 zu analysieren, wenn Sie eine Fünf-Spiel-Datei und zwei Spielsteine ​​haben.

    
Ethan Furman 06.01.2016, 19:42
quelle
7

Der pythonischste Weg ist das Logging -Modul. Es wurde in Kommentaren erwähnt, aber leider ohne dies hart genug zu betonen. Es gibt viele Gründe, warum Warnungen vorzuziehen sind:

    Das Modul
  1. Warnungen enthält Warnungen zu potenziellen code Problemen, nicht zu schlechten Benutzerdaten.
  2. Erster Grund ist eigentlich genug. : -)
  3. Das Logging-Modul bietet einen einstellbaren Schweregrad für Meldungen: Nicht nur Warnungen, sondern auch Fehler von Debug-Meldungen bis hin zu kritischen Fehlern können gemeldet werden.
  4. Sie können die Ausgabe des Protokollmoduls vollständig steuern. Nachrichten können nach Quelle, Inhalt und Schweregrad gefiltert, auf beliebige Weise formatiert und an verschiedene Ausgabeziele (Konsole, Pipes, Dateien, Speicher usw.) gesendet werden ...
  5. Das Logging-Modul trennt die tatsächlichen Fehler / Warnungen / Nachrichtenberichte und -ausgaben: Ihr Code kann Nachrichten des entsprechenden Typs generieren und muss sich nicht darum kümmern, wie sie dem Endbenutzer präsentiert werden.
  6. Logging-Modul ist der De-facto-Standard für Python-Code. Jeder nutzt es überall. Also, wenn Ihr Code es verwendet, wird es ein Kinderspiel, es mit 3rd-Party-Code zu kombinieren (was wahrscheinlich auch die Protokollierung verwendet). Nun, vielleicht etwas stärker als die Brise, aber definitiv kein Hurrikan der Kategorie 5. : -)

Ein grundlegender Anwendungsfall für das Protokollierungsmodul sieht folgendermaßen aus:

%Vor%

Dies wird Nachrichten wie:

ausgeben %Vor%

(vorausgesetzt, Ihr Modul heißt chess_parser.py)

Das Wichtigste ist, dass Sie in Ihrem Parsermodul nichts anderes tun müssen . Sie erklären, dass Sie das Logging-System verwenden, Sie verwenden einen Logger mit einem bestimmten Namen (wie in diesem Beispiel der Name Ihres Parser-Moduls) und Sie senden Warnmeldungen an diesen Logger. Ihr Modul muss nicht wissen, wie diese Nachrichten verarbeitet, formatiert und an den Benutzer gemeldet werden. Oder wenn sie überhaupt gemeldet werden. Beispielsweise können Sie das Protokollierungsmodul (normalerweise gleich zu Beginn des Programms) so konfigurieren, dass es ein anderes Format verwendet und es als Datei ablegt:

%Vor%

Und plötzlich, ohne Änderungen an Ihrem Modulcode, werden Ihre Warnmeldungen in einer Datei mit einem anderen Format gespeichert, anstatt auf dem Bildschirm auszudrucken:

%Vor%

Oder Sie können Warnungen unterdrücken, wenn Sie möchten:

%Vor%

Und die Warnungen Ihres Moduls werden vollständig ignoriert, während alle Fehler oder höheren Nachrichten von Ihrem Modul noch verarbeitet werden.

    
Lav 06.01.2016 12:46
quelle
3

Ich habe das Kopfgeld angeboten, weil ich gerne wissen würde, ob das wirklich der beste Weg ist. Allerdings schreibe ich auch einen Parser und deshalb brauche ich diese Funktionalität, und das ist, was ich mir ausgedacht habe.

Das Modul warnings ist genau das, was Sie wollen.

Was mich von Anfang an davon abgebracht hat, war, dass jede in den Dokumenten verwendete Beispielwarnung aussieht wie diese :

%Vor%

... was unerwünscht ist, weil ich nicht möchte, dass es ein UserWarning ist, möchte ich meinen eigenen benutzerdefinierten Warnnamen.

Hier ist die Lösung:

%Vor%

was ergibt:

%Vor%     
cat 03.01.2016 23:23
quelle
3

Ich bin mir nicht sicher, ob die Lösung pythonisch ist oder nicht, aber ich benutze sie ziemlich oft mit leichten Modifikationen: Ein Parser macht seine Arbeit innerhalb eines Generators und liefert Ergebnisse und einen Statuscode. Der empfangende Code trifft Entscheidungen mit fehlgeschlagenen Elementen:

%Vor%

Ein allgemeinerer Ansatz besteht darin, Designmuster zu üben. Eine vereinfachte Version von Beobachter (wenn Sie Rückrufe für bestimmte Fehler registrieren) oder eine Art Visitor (wo der Besucher Methoden zur Verarbeitung bestimmter Fehler hat, siehe SAX Parser für Einsichten) könnte eine klare und gut verstandene Lösung sein.

    
newtover 08.01.2016 22:52
quelle
0

Ohne Bibliotheken ist es schwierig, dies sauber zu machen, aber immer noch möglich.

Je nach Situation gibt es verschiedene Methoden, dies zu handhaben.

Methode 1:

Setzen Sie den gesamten Inhalt der while-Schleife in das Folgende:

%Vor%

Methode 2:

Wie bei Methode 1, außer dass mehrere try / avers-Dings vorhanden sind, also nicht zu viel Code & amp; Sie kennen den genauen Ort des Fehlers.

Sorry, in Eile, hoffe das hilft!

    
quelle