http://de.wikipedia.org/wiki/Assert
Hab eine Frage. Warum assert? Ist es nicht besser stattdessen eine "richtige" Exception auszulösen? Hab den oberen Artikel gelesen und soweit verstanden bloß frage ich mich nun wann assert angebracht ist und ob man das nicht zu oft benutzen sollte.
lg
`assert` - warum?
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hi sape!sape hat geschrieben:Warum assert?
``assert`` meldet mir meine eigenen persönlichen Fehler, die ich so beim Programmieren mache.
``assert`` hindert mich z.B. daran, die Zahl 100 zu übergeben, wenn ich nur eine Zahl zwischen 1 und 99 übergeben darf.
Viele dieser Prüfungen sind beim Programmieren noch recht wichtig, aber im fertigen Programm meist nicht mehr so sinnvoll. Ob jetzt der übergebene Parameter auch wirklich die eine oder andere Eigenschaft hat, ist für mich beim Programmieren wichtig. So merke ich frühzeitig, wenn ich etwas falsches übergebe.
``assert`` hat mich schon oft auf Fehler bei der Parameterübergabe aufmerksam gemacht. Deshalb setze ich es oft ein wenn die Qualität des Quellcodes sehr hoch sein muss und ich Fehler im Quellcode ziemlich früh bemerken möchte. Jetzt könnte man das typische DuckTyping-Argument nennen, aber ich denke, man muss immer abwiegen und selber entscheiden, ob eine eher lockere DuckTyping-Prüfung oder ein striktes ``isinstance`` angebracht ist.
``assert`` wird nicht ausgeführt, wenn Python mit ``-O`` gestartet wird. Man sollte aber auch im Hinterkopf behalten, dass die meisten Python-Programme NICHT mit ``-O`` ausgeführt werden.
Wenn man irgendwann alle ``assert``-Anweisungen los werden will, dann ist das mit einem Editor, der suchen kann, in wenigen Minuten erledigt.
``assert`` hat noch einen Vorteil: Man unterstützt dadurch die Code-Vervollständigung von WingIDE. Wenn WingIDE mal nicht weiß, was für ein Datentyp vorliegt und deshalb auch keine Code-Vervollständigung anbieten kann, dann hilft man einfach mit einem ``assert(isinstance())`` nach. Schon kann einem WingIDE beim Programmieren weiter helfen.
Fazit: ``assert`` hilft mir beim Programmieren Fehler zu vermeiden. ``assert`` ist nicht dazu gedacht, Benutzerfehler abzufangen.
lg
Gerold
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Mit `assert` testet man auf Sachen die unmöglich passieren können. Fehler in eigenem Quelltext, zum Beispiel Nachbedingungen oder Invarianten wie in dem Text ja auch beschrieben wird. Und es gibt auch keine sinnvolle Reaktion auf eine fehlgeschlagene Zusicherung. Man soll ja niemals nie sagen, aber `AssertionError` zu behandeln, ausser vielleicht um ein Errorlog oder so zu erstellen, ist ziemlich "falsch".sape hat geschrieben:http://de.wikipedia.org/wiki/Assert
Hab eine Frage. Warum assert? Ist es nicht besser stattdessen eine "richtige" Exception auszulösen? Hab den oberen Artikel gelesen und soweit verstanden bloß frage ich mich nun wann assert angebracht ist und ob man das nicht zu oft benutzen sollte.
Beispiele:
In einem RLE-Packer der Daten für den C64 komprimiert:
Code: Alles auswählen
if self._runCount > 255:
assert self._runCount < 0x10000
result.append('\x00')
result.append(chr(self._runCount & 0xff))
result.append(chr((self._runCount >> 8) & 0xff))
Aus einem Text-Parser der auf bestimmte Kommandozeilen reagiert:
Code: Alles auswählen
def _get_commandline_count(self):
"""Calculates number of processed command lines.
:returns: number of processed command lines.
:rtype: int
"""
result = self.line_number - self.textline_count
assert result >= 0
return result
Zusammenfassung von mir:
- Ausnahmen sind Fehler, die zur Laufzeit zwar nicht erwünscht, aber doch möglich sind, wie z.B. das Fehlen einer Datei; eben Ausnahmen vom normalen Programmablauf.
- Mit assert Anweisungen dagegen sollten zur Laufzeit des Programmes niemals fehlschlagen. Tun sie es doch, ist das eben nicht nur eine Ausnahmesituation, sondern ein kapitaler Fehler in der Programmlogik.
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Assert nutzen auch nur wenige Programmierer und auch dann eher selten. In den Quellcodes die mir so untergekommen sinnd, waren nie viele Asserts drinnen. Ich selbst nutze keine - Fehler in der Programmlogik sind bei mir ja ausgeschlossensape hat geschrieben:Ich werde das dann wohl wie bisher nicht nutzen
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Das denke ich mir auch oft. Häufig ist ein ``assert`` im Quelltext die Folge eines Fehlers, den ich an der Stelle mal entdeckt habe.
Nehme alles zurück. Nun benutze ich seit heute auch assert in dem Parser, der den Python Quellencode in einem AST anbildet. Da ist es nützlich für mich stellen zu "markieren" die einen bestimmten Zustand niemals annehmen dürfe (vorher hatte ich dafür eine überprüfung gemacht und dann ne Exception geworfen). Da der Parser noch nicht fertig ist kommt das bei bestimmten Konstellationen zustande und ich habe dann ein gutes Indiz wo ich noch was vergessen habe (Wie z.B. die Docstrings die sich über mehrere Zeilen erstrecken.).
Dank eurer Tipps von gestern weiß ich nun, dass an solchen stellen wo von einem Programmfehler ausgegangen werden muss, keine Exceptions als "Marker" hingehören Danke nochmals für eure Tipps.
Aber noch eine Frage habe ich:
Nehmt ihr die assert Bedingungen wenn eurer Code Perfekt funktioniert wider weck oder lässt ihr die einfach drin? Ich hab mir überlegt wenn mein Parser zu 99% Fehlerfrei funktioniert, das ich die asserts auskommentieren, zwecks Performance. Oder sollte ich mir wegen der Performance keine großen Gedanken machen?
lg
Dank eurer Tipps von gestern weiß ich nun, dass an solchen stellen wo von einem Programmfehler ausgegangen werden muss, keine Exceptions als "Marker" hingehören Danke nochmals für eure Tipps.
Aber noch eine Frage habe ich:
Nehmt ihr die assert Bedingungen wenn eurer Code Perfekt funktioniert wider weck oder lässt ihr die einfach drin? Ich hab mir überlegt wenn mein Parser zu 99% Fehlerfrei funktioniert, das ich die asserts auskommentieren, zwecks Performance. Oder sollte ich mir wegen der Performance keine großen Gedanken machen?
lg
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Hast du deswegen Performanceprobleme? Nein? Dann lass sie drin. Ich habe Zweifel, ob der Performanceunterschied mit und ohne assert mehr als ein halbes Prozent ausmacht.sape hat geschrieben:Ich hab mir überlegt wenn mein Parser zu 99% Fehlerfrei funktioniert, das ich die asserts auskommentieren, zwecks Performance. Oder sollte ich mir wegen der Performance keine großen Gedanken machen?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
asserts werden ignoriert, wenn man den Optimize Modus benutzt Siehe http://www.python-forum.de/topic-7472.html
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Oder siehe den Thread hier, denn gerold hat dies schon ein paar Posts früher geschriebenjens hat geschrieben:asserts werden ignoriert, wenn man den Optimize Modus benutzt Siehe http://www.python-forum.de/topic-7472.html
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Erstens, ich habe den post von Gerlod gelesen und zweitens, ich lese grundsätzlich alle posts (sogar mehrmals! Und das gilt auch für Threads bis ca. 20 Seiten.)!Leonidas hat geschrieben:Oder siehe den Thread hier, denn gerold hat dies schon ein paar Posts früher geschriebenjens hat geschrieben:asserts werden ignoriert, wenn man den Optimize Modus benutzt Siehe http://www.python-forum.de/topic-7472.html
Gerold hat ja auch geschrieben
.Wenn man irgendwann alle ``assert``-Anweisungen los werden will, dann ist das mit einem Editor, der suchen kann, in wenigen Minuten erledigt.
Daher stellte ich die Frage...
, weil ich wissen wollte ob ihr asserts bei 100%ig funktionierenden Code entfernt weil...Nehmt ihr die assert Bedingungen wenn eurer Code Perfekt funktioniert wider weck oder lässt ihr die einfach drin? Ich hab mir überlegt wenn mein Parser zu 99% Fehlerfrei funktioniert, das ich die asserts auskommentieren, zwecks Performance. Oder sollte ich mir wegen der Performance keine großen Gedanken machen?
a.) Sich die Performance erhöht? (ist ja nun geklärt -> ca. 0.5%)
b.) Um Toten-Code loszuwerden (ok, habe ich nicht erwähnt wo ich meinen post gerade lese ^^)
c.) Wegen anderen gründen?
So und nun Frieden meine Herren
Um ein wenig Spaß reinzubringen: Nun sehe ich das ich assert zu oft nutze (komischerweise nur im Parser). Hab da jetzt ne Ladung die ich nach funktionierenden Code doch entsorgen werde ^^
lg
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Nein, natürlich nicht 0,5%! 0,5% war ein Schätzwert von mir, womit ich andeuten wollte, dass es sehr wenig sein wird. Wie viel Prozent es tatsächlich sind, müsstest du mit dem Profiler nachmessen. Aber große Unterschiede sind eher nicht zu erwarten. Außer du hast in jeder zweiten Zeile ein Assert und/oder der Assert-Code wird sehr oft ausgeführt.sape hat geschrieben:a.) Sich die Performance erhöht? (ist ja nun geklärt -> ca. 0.5%)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Es kommt letztendlich auch auf den Code an, der im ``assert`` ausgeführt wird. Da können schliesslich beliebige Ausdrücke stehen, auch solche die wirklich viel Code ausführen, eine Verbindung zu einer Datenbank aufbauen oder ähnliche Zeitfresser.
Zumindest für ``assert``s die Nachbedingungen oder Klasseninvarianten prüfen, kann man Unit-Tests schreiben. Dann geht der Test nicht ganz verloren, falls man das ``assert`` entfernt, sondern wird nur für ausgewählte Testfälle ausgeführt.
Zumindest für ``assert``s die Nachbedingungen oder Klasseninvarianten prüfen, kann man Unit-Tests schreiben. Dann geht der Test nicht ganz verloren, falls man das ``assert`` entfernt, sondern wird nur für ausgewählte Testfälle ausgeführt.
Oh Hmm, wie schon geschrieben rede ich hier von einem Parser. Da kannst du dir ja vorstellen wie oft verschiedene Bereiche ausgeführt werden und zwar _sehr_ oft.Leonidas hat geschrieben:oder der Assert-Code wird sehr oft ausgeführt.
So sieht z.B. der Bereich, im `AstGenerator` aus der für die Funktions-/Klassendefinition zuständig ist:
http://paste.pocoo.org/show/501/
Wie gesagt, die Asserts sind für mich an diesen stellen Überlebenswichtig, um mich darauf hinzuweisen, wo eventuell noch was fehlt bzw. was ich nicht mitberücksichtigt habe zu Implementieren!
Wie ich schon geschrieben habe, sind alle Abschnitte (_add2node__XYZ) "irgendwie auch voneinander abhängig". Schlecht zu beschrieben, ohne näher auszuholen (könnte ich zwar jetzt mit einem Konkreten Beispiel machen (wo ncoh was fehlt) aber das würde den Rahmen hier sprengen.
Ich mache, wenn das Modul "ast.py" fertig ist, sowieso einen thread auf (PyMetric und PySource2UML).
Die runfunktion sieht so aus:
http://paste.pocoo.org/show/502/
Was ist nun für mich die Konsequenz mit den asserts die ja 1K mal aufgerufen werden? Doch auskommentieren oder?
EDIT:
-O ist keine Option, weil unter windows die Zeile #!/usr/bin/python -O nicht ausgewertet wird.
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
...um noch einen drauf zu setzen.
Hier habe ich ein Codebeispiel, das ziemlich gut demonstriert, wofür *ich* ``assert`` meistens einsetze -- um Parameter auf Gültigkeit zu überprüfen. In diesem Beispiel (welches aus einer Klasse heraus gerissen wurde und deshalb auch auf Methoden zugreift, die nicht im Beispiel enthalten sind!) wird eine XML-Datei erstellt. Falls ein falscher Wert als Parameter übergeben wird, würde mein Programm zwar weiterhin korrekt funktionieren -- aber das Programm, dem die XML-Datei übergeben wird -- würde mir einen Kropf an den Hals wünschen. Die Werte die als Parameter übergeben werden, werden nicht vom Benutzer übergeben, sondern vom Programmierer des Client-Programms. Ich fange also mögliche Programmierfehler per ``assert`` ab, um den Programmierer des Clientprogramms (das bin leider auch ich) frühzeitig auf falsch übergebene Parameter hinzuweisen.
Zur Erklärung der Methode:
In Zeile 65 ``(root, short_filename) = self._get_xml_base()`` wird bereits der Header der XML-Datei generiert. Der Rest des Codes fügt XML-Tags (nach Bedarf) hinzu. Die ``assert``-Anweisungen dienen zum Prüfen der übergebenen Parameter.
In Zeile 159 übergebe ich den XML-Root an eine Methode um daraus gültiges XML zu generieren und in eine Datei zu schreiben.
``et`` kommt von ``from elementtree import ElementTree as et``.
http://paste.pocoo.org/show/504/
Wenn jemand einen Fehler entdeckt --> bitte melden.
lg
Gerold
Hier habe ich ein Codebeispiel, das ziemlich gut demonstriert, wofür *ich* ``assert`` meistens einsetze -- um Parameter auf Gültigkeit zu überprüfen. In diesem Beispiel (welches aus einer Klasse heraus gerissen wurde und deshalb auch auf Methoden zugreift, die nicht im Beispiel enthalten sind!) wird eine XML-Datei erstellt. Falls ein falscher Wert als Parameter übergeben wird, würde mein Programm zwar weiterhin korrekt funktionieren -- aber das Programm, dem die XML-Datei übergeben wird -- würde mir einen Kropf an den Hals wünschen. Die Werte die als Parameter übergeben werden, werden nicht vom Benutzer übergeben, sondern vom Programmierer des Client-Programms. Ich fange also mögliche Programmierfehler per ``assert`` ab, um den Programmierer des Clientprogramms (das bin leider auch ich) frühzeitig auf falsch übergebene Parameter hinzuweisen.
Zur Erklärung der Methode:
In Zeile 65 ``(root, short_filename) = self._get_xml_base()`` wird bereits der Header der XML-Datei generiert. Der Rest des Codes fügt XML-Tags (nach Bedarf) hinzu. Die ``assert``-Anweisungen dienen zum Prüfen der übergebenen Parameter.
In Zeile 159 übergebe ich den XML-Root an eine Methode um daraus gültiges XML zu generieren und in eine Datei zu schreiben.
``et`` kommt von ``from elementtree import ElementTree as et``.
http://paste.pocoo.org/show/504/
Wenn jemand einen Fehler entdeckt --> bitte melden.
lg
Gerold
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Profiler anwerfen. Übrigens ist assert ein Keyword und keine Funktion, daher kannst du die Klammern weglassen.sape hat geschrieben:Was ist nun für mich die Konsequenz mit den asserts die ja 1K mal aufgerufen werden? Doch auskommentieren oder?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Hier aml ein Screenshot von dem kleinen Tool mit dem ich überprüfen kann, ob alle "Abdrücke" im Python Sourcefile auch in den richtigen Knotenpunkten sind. Seit dem ich das für meine `AstGenerator` geschrieben hab, habe ich sehr viele Bugs beheben können BTW: Die grauen kästchen kann man mit einem Rechstklick auf einer Node öffne
Daraufklicken um zu einer vergrößerten Ansicht zu gelangen
Daraufklicken um zu einer vergrößerten Ansicht zu gelangen
Das kommt darauf an was *sehr* oft bedeutet. Ein paar tausend mal muss nicht oft sein, auch ein paar zehntausend mal nicht. Wenn man nicht gerade einen universellen Parser schreibt, der O(n^3) Zeit benötigt, mit `n` der Anzahl der Eingabesymbole, dann sollten ein paar einfache ``assert``s pro verarbeitetem Symbol kein Problem sein.sape hat geschrieben:Oh Hmm, wie schon geschrieben rede ich hier von einem Parser. Da kannst du dir ja vorstellen wie oft verschiedene Bereiche ausgeführt werden und zwar _sehr_ oft.Leonidas hat geschrieben:oder der Assert-Code wird sehr oft ausgeführt.
1K ist grundsätzlich für einfache Prüfungen IMHO nicht viel. Du kannst den Code ja mal mit und ohne ``-O`` laufen lassen und vergleichen, ob sich das überhaupt bemerkbar macht. Und wenn es sich bemerkbar macht, dann musst Du entscheiden ob der Gewinn in der Geschwindigkeit gross genug ist, um auf die ``assert``s zu verzichten. Dann bleibt noch die Frage auf welche man verzichten möchte. Es gibt sicher welche, die wichtiger sind als andere und es gibt auch welche, die mehr zur Laufzeit beitragen als andere. Eins das das Programm 0.00001% langsamer macht muss man nicht unbedingt rauswerfen, andererseits kann ein Zeitfresser auch wichtig genug sein um ihn zu behalten.Was ist nun für mich die Konsequenz mit den asserts die ja 1K mal aufgerufen werden? Doch auskommentieren oder?