Fehlerausgabe bei eigenen Modulen/Bibliotheken

classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

Fehlerausgabe bei eigenen Modulen/Bibliotheken

Johannes Markert
Grüße an die Python-Gemeinschaft,

ich entwickle zur Zeit ein kleines Modul, vorerst für den privaten
Gebrauch; wenn es ausgereift ist,
habe ich vor dieses eventuell auch zu veröffentlichen.

Mich stellt sich aber momentan eine Frage.
Wie kann ich in Python professionell eine Fehlerausgabe implementieren.
D.h. wenn ein Programmierer in seinem Projekt dieses Modul einbindet und
dabei zum Beispiel falsche Parameter
an Modulfunktionen übergibt.
Dann soll noch währender der Interpretierung und/oder der Ausführung
seines Quellcodes das Programm stoppen und eine
Fehlermeldung ausgegeben werden.

In der Form:

     File "dateiXY", line XY, in ModulXY
     TypeError: Funktion_mit_falschen_Parametern():
     received integer, tupel required

Mit anderen Worten eine Typenprüfung.

Als weiteres Beispiel fällt mir noch ein, wenn die Werteanzahl einer
Liste oder eines Tupel zu gering/groß ist.
Auch hier sollte entsprechend eine Fehlermeldung erscheinen.


Diese Beispiele sollen nur verdeutlichen, was ich meine.
Mir geht es also um eine allgemeine Herangehensweise des Problems.
Gibt es dafür eine Lösung in Python?

Danke!

Mit freundlichen Grüßen,
Johannes Markert





_______________________________________________
python-de maillist  -  [hidden email]
http://python.net/mailman/listinfo/python-de
Reply | Threaded
Open this post in threaded view
|

Re: Fehlerausgabe bei eigenen Modulen/Bibliotheken

Bugzilla from dasdasich@googlemail.com
Wenn Nutzer irgendwas übergibt was nicht passt wird eine Exception
auftreten und der Nutzer schaut in die Dokumentation deines Moduls, was
er eigentlich auch hätte gleich machen können.


_______________________________________________
python-de maillist  -  [hidden email]
http://python.net/mailman/listinfo/python-de
Reply | Threaded
Open this post in threaded view
|

Re: Fehlerausgabe bei eigenen Modulen/Bibliotheken

Hartmut Goebel
In reply to this post by Johannes Markert
Hallo Johannes,

> Wie kann ich in Python professionell eine Fehlerausgabe implementieren.
> D.h. wenn ein Programmierer in seinem Projekt dieses Modul einbindet und
> dabei zum Beispiel falsche Parameter an Modulfunktionen übergibt.

Es geht Dir also um Programmierfehler. Das ist ein wichtiger Punkt, denn
Programmierern kann (und muss) man Fehler ganz anders melden als Anwendern.

Und Programmierfehler melden ist ganz einfach, indem Du eine Exception
auslöst (Befehl "raise"). Unten ein Beispiel, wie Du (nach der Lehre der
Programmiersprache Eiffel) die Vorbedingungen prüfst.

> Dann soll noch währender der Interpretierung und/oder der Ausführung
> seines Quellcodes das Programm stoppen und eine
> Fehlermeldung ausgegeben werden.
>
> In der Form:
>
>     File "dateiXY", line XY, in ModulXY
>     TypeError: Funktion_mit_falschen_Parametern():
>     received integer, tupel required

Ungefähr das gibt der Python-Interpreter aus, wenn eine Exception
ausgelöst wird, die nicht abgefangen wird.

Mehr dazu findest Du hier: <http://docs.python.org/tutorial/errors.html>

Und nun das Beispiel:

def ich_teste_selbst(zahl, elemente):
     assert isintance(zahl, int)
     assert len(elemente) = 4, "'elemente' muss 4 Elemente haben"

Die Anweisung "assert" ist dabei nicht anderes als
   if not <bedingung>: raise AssertionError
siehe auch
<http://docs.python.org/reference/simple_stmts.html#the-assert-statement>.

Allerdings werden solche Prüfungen in Python eher selten. Denn ein
Programmierfehler kommt auch zum Vorschein in diesem Beispiel:

def ich_lasse_testen(zahl, elemente):
     zahl = zahl / 5  # erlaubt auch int, long, float
     host, port, user, password = elemente # müsen 4 Elemente sein

Wenn Du das aufrufst:
>>> ich_lasse_testen('Hallo', (1,2,3,4))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in ich_lasse_testen
TypeError: unsupported operand type(s) for /: 'str' and 'int'

(Wobei man im letzteren Fall vielleicht besser ein dict oder eine
einfache Klasse verwenden würde.)

--
Schönen Gruß - Regards
Hartmut Goebel
Dipl.-Informatiker (univ.), CISSP, CSSLP

Goebel Consult
Spezialist für IT-Sicherheit in komplexen Umgebungen
http://www.goebel-consult.de

Monatliche Kolumne: http://www.cissp-gefluester.de/
Goebel Consult mit Mitglied bei http://www.7-it.de


_______________________________________________
python-de maillist  -  [hidden email]
http://python.net/mailman/listinfo/python-de

smime.p7s (6K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Fehlerausgabe bei eigenen Modulen/Bibliotheken

Stefan Schwarzer-2
In reply to this post by Johannes Markert
Hallo Johannes,

On 2010-08-05 00:11, Johannes Markert wrote:
> Grüße an die Python-Gemeinschaft,

Grüße zurück! ;-)

> ich entwickle zur Zeit ein kleines Modul, vorerst für den privaten
> Gebrauch; wenn es ausgereift ist,
> habe ich vor dieses eventuell auch zu veröffentlichen.
>
> Mich stellt sich aber momentan eine Frage.
> Wie kann ich in Python professionell eine Fehlerausgabe implementieren.
> D.h. wenn ein Programmierer in seinem Projekt dieses Modul einbindet und
> dabei zum Beispiel falsche Parameter
> an Modulfunktionen übergibt.
> [...]

Man unterscheidet üblicherweise zwischen unvorhersehbaren
Fehlern, zum Beispiel einer fehlenden Datei, und
Programmierfehlern. Zu letzteren würde auch ein falscher
Aufruf deiner Modulfunktion zählen.

Die unvorhersehbaren Fehler werden üblicherweise behandelt,
indem man eine "High-Level"-Ausnahme wirft. Was man eher
nicht machen sollte, ist, einen IndexError oder KeyError
einfach "durchzulassen". Das hätte den Nachteil, dass der
Aufrufer, wenn du mal einen Container in der Implementierung
deines Moduls von einer Liste auf ein Dictionary änderst,
plötzlich eine andere Ausnahme bekommt.

Nun zu deiner eigentlichen Frage. :-) Programmierfehler
werden im Allgemeinen in Python gar nicht behandelt, da man
davon ausgeht, dass ein Benutzer deiner Bibliothek ohnehin
testen muss, auch um logische Fehler zu finden. Wenn eine
Funktion zum Beispiel sinus heißt, aber den Cosinus des
Arguments zurückgibt, nützt der korrekte Aufruf mit einem
Float-Parameter auch nichts. ;-)

Python als Sprache verzichtet bewusst auf Typprüfungen,
deshalb ist es auch nicht sinnvoll, das nachzubilden. Du
kannst aber, quasi als "ausführbare Dokumentation",
assert-Anweisungen verwenden. Das würde ich aber nur tun,
wenn du bestimmte Fehler regelrecht erwartest; routinemäßig
alle denkbaren falschen Aufrufe mit assert absichern würde
ich nicht.

Ganz konkrete Typen zu verlangen, schränkt außerdem die
Aufrufmöglichkeiten oft unnötig ein. Die allermeisten
Funktionen, die ein Tupel vertragen, laufen zum Beispiel
auch mit einer Liste. _Falls_ du eine Typprüfung vornehmen
willst, verwende isinstance statt mit einem ganz konkreten
Typ zu vergleichen, denn isinstance(obj, Class) gibt auch
einen wahren Wert zurück, wenn obj zu einer von Class
abgeleiteten Klasse gehört.

> Dann soll noch währender der Interpretierung und/oder der Ausführung
> seines Quellcodes das Programm stoppen und eine
> Fehlermeldung ausgegeben werden.

Das wäre mit assert-Anweisungen gegeben. Aber auch die
meisten anderen Aufruf-Probleme machen sich schnell durch
AttributeError, IndexError etc. bemerkbar.

> In der Form:
>
>      File "dateiXY", line XY, in ModulXY
>      TypeError: Funktion_mit_falschen_Parametern():
>      received integer, tupel required
>
> Mit anderen Worten eine Typenprüfung.

Siehe oben.

> Als weiteres Beispiel fällt mir noch ein, wenn die Werteanzahl einer
> Liste oder eines Tupel zu gering/groß ist.
> Auch hier sollte entsprechend eine Fehlermeldung erscheinen.

Auch das solltest du, falls es in die Kategorie
Programmierfehler fällt, mit assert behandeln. Ein
fehlgeschlagenes assert löst einen AssertionError aus.

Wenn du es "nicht lassen kannst" eine Typ-Prüfung zu
implementieren, kannst du eine ProgrammingError-Exception
definieren und diese im Fehlerfall mit möglichst
ausführlichen Informationen auslösen. Eine scheinbare
Parallele gibt es bei der Python-Datenbank-API, bei der ein
ProgrammingError ausgelöst werden kann. Diese Exception
bezieht sich aber eher auf Fehler, die in der Abstimmung von
Programm und Datenbank liegen, zum Beispiel wenn gegen ein
Constraint wie NOT NULL oder UNIQUE verstoßen wird. Diese
Dinge sind ebenso wie auch externe Daten nicht vorhersehbar,
fallen also wohl nicht in die gleiche Kategorie wie
"offensichtlich" fehlerhafte Aufrufe.

Um das ganze Kopfzerbrechen um falsche Aufrufe möglichst
weitgehend zu vermeiden, solltest du von vornherein auf eine
für deine Modul-Funktionalität möglichst "natürliche" API
achten. Ich könnte mir vorstellen, dass du bei deiner Frage
schon bestimmte potenziell fehleranfällige Schnittstellen im
Sinn hattest. In dem Fall frag ruhig konkret nach Rat für
die Gestaltung der Aufruf-Schnittstelle.

Viele Grüße
Stefan

_______________________________________________
python-de maillist  -  [hidden email]
http://python.net/mailman/listinfo/python-de
Reply | Threaded
Open this post in threaded view
|

Re: Fehlerausgabe bei eigenen Modulen/Bibliotheken

Mike Abel
In reply to this post by Johannes Markert
Hallo Johannes,

falls du es noch nicht gemacht hast, schau dir mal die Module an,
welche Python mitbringt. Man lernt viel durch das Studium von anderen.

Grüße
Mike


_______________________________________________
python-de maillist  -  [hidden email]
http://python.net/mailman/listinfo/python-de
Reply | Threaded
Open this post in threaded view
|

Fehlerbehandlung während oder nach Grundimplementation?

Johannes Markert
Wow,

ich bin echt beeindruckt von den vielen ausführlichen Antworten.
Sie haben mir wirklich sinnvolle Denkanstöße gegeben. Ich danke dafür
herzlich.

Und weil das so super geklappt hat, schließe ich gleich eine weitere
Frage an: ;-)

Nach euren Erfahrungen ...
Was ist besser: Die Fehlerbehandlung gleich während der Planung des
Programms mit zu berücksichtigen und im Quelltext zu verankern oder
nach der Grundimplementation diese nachträglich einzubauen?

Gruß,
Johannes

_______________________________________________
python-de maillist  -  [hidden email]
http://python.net/mailman/listinfo/python-de
Reply | Threaded
Open this post in threaded view
|

Re: Fehlerbehandlung während oder nach Grundimplementation?

Andreas Jung-5
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Johannes Markert wrote:

> Wow,
>
> ich bin echt beeindruckt von den vielen ausführlichen Antworten.
> Sie haben mir wirklich sinnvolle Denkanstöße gegeben. Ich danke dafür
> herzlich.
>
> Und weil das so super geklappt hat, schließe ich gleich eine weitere
> Frage an: ;-)
>
> Nach euren Erfahrungen ...
> Was ist besser: Die Fehlerbehandlung gleich während der Planung des
> Programms mit zu berücksichtigen und im Quelltext zu verankern oder
> nach der Grundimplementation diese nachträglich einzubauen?
>
Da gibt es sicherlich keine goldenen Regel. Bestimmte Checks wird man
sicherlich schon von vornerein einbauen - andere erst später, wenn man
rausfindet, dass man seinen Code robuster machen muss.

- -aj
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (Darwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkxa0rUACgkQCJIWIbr9KYzX8QCaA9etYF/fpPCMO+8YzACzV/LY
eYIAnjK7VDP9SBLyPOLAGug7ahTDQceO
=/+2H
-----END PGP SIGNATURE-----

_______________________________________________
python-de maillist  -  [hidden email]
http://python.net/mailman/listinfo/python-de

lists.vcf (331 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Fehlerbehandlung während oder nach Grundimplementation?

Sebastian Bechtel
In reply to this post by Johannes Markert
Hallo,

ganz klar während der Entwicklung.

Anders ist das ja auch gar nicht wirklich möglich, den wenn du Fehler behandelst kommt ja ein ganz anderer Programmfluss zustande als ohne.

Anders ist es natürlich wenn du erst Prototyping betreibst, dann kannst du auf die Fehlerbehandlung verzichten, solltest aber dann auch bei der eigentlichen Implementierung von Grund auf neu ansetzten.

Gruß Sebastian

Am 05.08.2010 um 16:38 schrieb Johannes Markert:

> Wow,
>
> ich bin echt beeindruckt von den vielen ausführlichen Antworten.
> Sie haben mir wirklich sinnvolle Denkanstöße gegeben. Ich danke dafür herzlich.
>
> Und weil das so super geklappt hat, schließe ich gleich eine weitere Frage an: ;-)
>
> Nach euren Erfahrungen ...
> Was ist besser: Die Fehlerbehandlung gleich während der Planung des Programms mit zu berücksichtigen und im Quelltext zu verankern oder
> nach der Grundimplementation diese nachträglich einzubauen?
>
> Gruß,
> Johannes
>
> _______________________________________________
> python-de maillist  -  [hidden email]
> http://python.net/mailman/listinfo/python-de


_______________________________________________
python-de maillist  -  [hidden email]
http://python.net/mailman/listinfo/python-de
Reply | Threaded
Open this post in threaded view
|

Re: Fehlerbehandlung während oder nach Grundimplementation?

Stefan Schwarzer-2
In reply to this post by Johannes Markert
Hallo Johannes,

On 2010-08-05 16:38, Johannes Markert wrote:
> ich bin echt beeindruckt von den vielen ausführlichen Antworten.
> Sie haben mir wirklich sinnvolle Denkanstöße gegeben. Ich danke dafür
> herzlich.

bitteschön. :)

> Und weil das so super geklappt hat, schließe ich gleich eine weitere
> Frage an: ;-)
>
> Nach euren Erfahrungen ...
> Was ist besser: Die Fehlerbehandlung gleich während der Planung des
> Programms mit zu berücksichtigen und im Quelltext zu verankern oder
> nach der Grundimplementation diese nachträglich einzubauen?

Ich würde folgendermaßen vorgehen:

1. Je nach Erfahrung mit OOP und Umfang/Komplexität der
   Software das OO-Design ggf. vor dem Schreiben des Codes
   überlegen. Dabei auch schon an mögliche Fehlerbedingungen
   denken.

2. Bevor du irgendwelchen Produktionscode schreibst, schreib
   etwas Code, wie er den Produktionscode benutzen würde.
   Spiel ein bisschen mit der API rum, die du dir überlegt
   hast. Schau dir an, ob sich dein Code in einfachen,
   komplizierten und Fehler-Fällen "angenehm anfühlt". Heb
   diesen Code auf; evtl. kannst du ihn noch für
   automatisierte Tests verwenden.

3. Abwechselnd Testcode und Produktionscode schreiben (erst
   die Tests; "test-driven development"). Wenn ich mir noch
   gar nicht sicher bin, ob sich etwas so wie ich mir
   vorstelle, überhaupt implementieren lässt, schreibe ich
   auch manchmal den Produktionscode zuerst.

4. Wenn sich später herausstellt, dass es irgendwo hakt,
   also sich die API kompliziert anfühlt, die Probleme
   möglichst früh beheben bzw. refaktorieren. Hier helfen
   wieder die automatisierten Tests.

Viele Grüße
Stefan

_______________________________________________
python-de maillist  -  [hidden email]
http://python.net/mailman/listinfo/python-de
Reply | Threaded
Open this post in threaded view
|

Re: Fehlerausgabe bei eigenen Modulen/Bibliotheken

Sebastian Bechtel
In reply to this post by Johannes Markert
Hallo,

für mich als Python Neuling hat sich genau die selbe Frage auch gestellt. Deshalb möchte ich mal meine These vorstellen, warum es "pythonisch" ist, keine Type Checks zu machen ;-)

Ich denke nämlich das Python hier gar nicht aus dem Raster fällt. Wenn man mich Fragen würde, ob ich sonst immer Type Checks gemacht habe, dann würde ich sofort sagen "Ja, immer". In Wirklichkeit habe ich es aber gar nicht wirklich gemacht, sondern ich habe auf Interfaces und Abstrakte Klassen gecheckt.

Durch diese Möglichkeit konnte ich flexible Architekturen entwerfen, ohne dabei auf Checks verzichten zu müssen.

Nun ist in Python alles etwas flexibler und Interfaces und abstrakte Klassen gibt es nicht (oder ich habe sie zumindest so direkt noch nicht gefunden).

Daher muss man eben mehr auf die Vernunft des Clients bauen.

Allerdings nun auf einzelne Klassen zu prüfen wäre der falsche Weg, in anderen Sprachen würde man es ja auch nicht machen.

Mein Wort zum Donnerstag ;-)

Seht ihr das auch so, oder was ist eure Meinung dazu?

Gruß Sebastian

Am 05.08.2010 um 00:11 schrieb Johannes Markert:

> Grüße an die Python-Gemeinschaft,
>
> ich entwickle zur Zeit ein kleines Modul, vorerst für den privaten Gebrauch; wenn es ausgereift ist,
> habe ich vor dieses eventuell auch zu veröffentlichen.
>
> Mich stellt sich aber momentan eine Frage.
> Wie kann ich in Python professionell eine Fehlerausgabe implementieren.
> D.h. wenn ein Programmierer in seinem Projekt dieses Modul einbindet und dabei zum Beispiel falsche Parameter
> an Modulfunktionen übergibt.
> Dann soll noch währender der Interpretierung und/oder der Ausführung seines Quellcodes das Programm stoppen und eine
> Fehlermeldung ausgegeben werden.
>
> In der Form:
>
>    File "dateiXY", line XY, in ModulXY
>    TypeError: Funktion_mit_falschen_Parametern():
>    received integer, tupel required
>
> Mit anderen Worten eine Typenprüfung.
>
> Als weiteres Beispiel fällt mir noch ein, wenn die Werteanzahl einer Liste oder eines Tupel zu gering/groß ist.
> Auch hier sollte entsprechend eine Fehlermeldung erscheinen.
>
>
> Diese Beispiele sollen nur verdeutlichen, was ich meine.
> Mir geht es also um eine allgemeine Herangehensweise des Problems.
> Gibt es dafür eine Lösung in Python?
>
> Danke!
>
> Mit freundlichen Grüßen,
> Johannes Markert
>
>
>
>
>
> _______________________________________________
> python-de maillist  -  [hidden email]
> http://python.net/mailman/listinfo/python-de


_______________________________________________
python-de maillist  -  [hidden email]
http://python.net/mailman/listinfo/python-de
Reply | Threaded
Open this post in threaded view
|

Re: Fehlerbehandlung während oder nach Grundimplementation?

Hartmut Goebel
In reply to this post by Stefan Schwarzer-2
Am 05.08.2010 20:30, schrieb Stefan Schwarzer:

> Ich würde folgendermaßen vorgehen:

Schöne Beschreibung. Besonders das mit dem "sich die API kompliziert
anfühlt" :-) Setzt allerdings Erfahrung voraus.

--
Schönen Gruß - Regards
Hartmut Goebel
Dipl.-Informatiker (univ.), CISSP, CSSLP

Goebel Consult
Spezialist für IT-Sicherheit in komplexen Umgebungen
http://www.goebel-consult.de

Monatliche Kolumne: http://www.cissp-gefluester.de/
Goebel Consult mit Mitglied bei http://www.7-it.de


_______________________________________________
python-de maillist  -  [hidden email]
http://python.net/mailman/listinfo/python-de

smime.p7s (6K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Fehlerausgabe bei eigenen Modulen/Bibliotheken

Hartmut Goebel
In reply to this post by Sebastian Bechtel
Hallo,

Am 05.08.2010 22:10, schrieb Sebastian Bechtel:

> für mich als Python Neuling hat sich genau die selbe Frage auch gestellt. Deshalb
> möchte ich mal meine These vorstellen, warum es "pythonisch" ist,
keine Type
> Checks zu machen ;-)
[...]
> Nun ist in Python alles etwas flexibler und Interfaces und abstrakte Klassen
> gibt es nicht (oder ich habe sie zumindest so direkt noch nicht gefunden).
[...]
> Allerdings nun auf einzelne Klassen zu prüfen wäre der falsche Weg, in
> anderen Sprachen würde man es ja auch nicht machen.

Die Typechecks muss man ja auch nicht selbst machen, das macht ja Python
für einen, wenn es nötig ist.

Anderer Programmiersprachen haben "Interfaces" und man kann/muss testen,
ob einen Klasse dieses Interface implementiert. In Python spart man sich
das und macht statt dessen "duck-typing"
<http://de.wikipedia.org/wiki/Duck-Typing>.

Das funktioniert grob so: Wenn ich ein Element an ein "Liste"-Objekt
anhängen will, also eigentlich Elemente sammeln will, dann muss die
"Liste" dafür ja nur die Methode "append()" unterstützen. Wenn ein
Objekt übergeben wird, das append nicht kann, dann fällt das beim Testen
auf.

Die Philosophie ist die: Warum bei 100% der Objekte prüfen, ob sie eine
bestimmte Klasse haben oder ein bestimmtes Interface implementieren,
wenn doe (negative) Prüfung nur bei 0,0001% relevant ist? Da ist es
billiger (aka schneller) im Fehlerfall zu schreien.

[Bei einer statisch typisierten Sprach wie Java sind solche Tests eher
sinnvoll. Dann da kann der Compiler zur Übersetzungszeit prüfen.]

Abstrakte Klassen sind einfach Klassen, bei denen nicht alle Methoden
implementiert sind. Da Python keine Interfaces kennt, mache ich das
üblicherweise so:

class X:
   def tu_was(self, was, das, nocheines):
      raise NotImplementedError

Ab Python 2.6 gibt es auch das Modul `abc`, mit dem man Abstract Base
Classes entsprechend markieren kann.
<http://docs.python.org/library/abc.html>

--
Schönen Gruß - Regards
Hartmut Goebel
Dipl.-Informatiker (univ.), CISSP, CSSLP

Goebel Consult
Spezialist für IT-Sicherheit in komplexen Umgebungen
http://www.goebel-consult.de

Monatliche Kolumne: http://www.cissp-gefluester.de/
Goebel Consult mit Mitglied bei http://www.7-it.de


_______________________________________________
python-de maillist  -  [hidden email]
http://python.net/mailman/listinfo/python-de

smime.p7s (6K) Download Attachment