debugging methoden

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
Costi
User
Beiträge: 545
Registriert: Donnerstag 17. August 2006, 14:21

was fuer endbuging methoden gibt es eigentlich noch, auser alle wichtige variablen zu printen

danke
cp != mv
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Setzen von Breakpoints, Tracen von Variablen, in anderen Programmiersprachen kann man auch die Speicherverwaltung nach Memory-Leaks durchsuchen (zum Beispiel mit Valgrind), außerdem kann man Programme auch noch Profilen um zu sehen, wie der Programmablauf nun endlich, sequentiell ausgesehen hat und dort ablesen wie lange alles gedauert hat.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

Den Quelltext so zu schreiben, dass man im Interpretierer die einzelnen Funktionen "live" ausprobieren kann und Unit-Tests helfen auch.
Costi
User
Beiträge: 545
Registriert: Donnerstag 17. August 2006, 14:21

[geloescht]
cp != mv
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Ich hab deinen Code mal ins Pastebin ausgelagert und muss sagen, dass der Code so ziemlich von vorne bis hinten schrott ist.

Wieso das?

Du nutzt Klassen, ohne dasss ein Grund dafür existiert, die Klasse Utils braucht kein Mensch, das sind alles einzelne Funktionen. Du baust einen HTTPServer, obwohl ein wesentlich besserer bereits in der Stdlib ist. Du nutzt Inline-Kommentare, du wirfst HTML-Code wahlfrei mit Python-Code zusammen, Namen wie ph sagen gar nichts aus, die spärlichen Kommentare dokumentieren überhaupt nichts.

Fazit: Debuggen zwecklos, neuschreiben.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Costi
User
Beiträge: 545
Registriert: Donnerstag 17. August 2006, 14:21

hab mir jetzt die letzten schoko reserven vom nicolaus aufgebraucht, scooter angemacht und siehe da: http://pastebin.com/845451
bug fixed ( ; (lag nicht nur an "{"cmd": "dummy0", "cmdResp": "dummy1", "cmd": "dummy2"}")

wie wuerdest es du den ungefaehr schreieben?
cp != mv
cracki
User
Beiträge: 72
Registriert: Montag 25. Dezember 2006, 05:01

wow schreib den code neu!

erster tipp:

Code: Alles auswählen

somedict.has_key(key) == (key in somedict)
und lass die klassen weg, wir sind hier nicht in java.
...meh...
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

cracki hat geschrieben:[...]
und lass die klassen weg, wir sind hier nicht in java.
Was genau ist an diesem Satz nicht richtig? Morgen schreibe ich zu dieser Pauschalisierung was! -> Also ich liefere auch eine Begründung dazu und stelle nicht pauschal ein nicht haltbare Behauptung auf.
cracki
User
Beiträge: 72
Registriert: Montag 25. Dezember 2006, 05:01

sape:
(1) wir sind hier nicht in java, weil python != java. man vergleiche die grammars. :>
(2) er missbraucht die eine klasse (utils) anscheinend als namespace
(3) fuer dieses problem sehe ich nicht, wie eigene klassen zu rechtfertigen waeren. die webserverklasse koennte er mit stdlib sachen locker ausduennen

ich bin gespannt auf morgen/heute, wenn du was zu meiner pauschalisierung (welche eigentlich?) sagen wirst.
...meh...
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

sape hat geschrieben:Morgen schreibe ich zu dieser Pauschalisierung was! -> Also ich liefere auch eine Begründung dazu und stelle nicht pauschal ein nicht haltbare Behauptung auf.
An dieser Stelle ist es nicht pauschal. Wie ich schon geschrieben habe, ist die Utils-Klasse vällig sinnentleer. Für sowas erstellt man ein Modul utils.py und fertig.

Kann mir jemand sagen, was dieser Code überhaupt machen soll?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

Einrücken mit Tabs kann zu schwer zu lokalisierenden Fehlern führen wenn irgendwann einmal Tabs und Leerzeichen gemischt vorkommen. Ausserdem ist die "Länge" von Tabs normalerweise 8. Damit ist der Quelltext sehr tief eingerückt, vor allem wenn mehr als zwei oder drei Schleifen oder ``if``-Anweisungen geschachtelt werden. Womit wir bei der Zeilenlänge wären, die 80 Zeichen nicht überschreiten sollte. Vor ``+=`` fehlt im Quelltext fast immer ein Leerzeichen.

Inline-Kommentare wurden schon angesprochen. Den bei `Season.addCmds()` könnte man zum Beispiel prima als Docstring verwenden.

Die Namen sind nicht PEP 8 konform. Die Methoden in `Utils` könnten alles Funktionen sein. In `Utils.check()` wird der Name `dict` benutzt und verdeckt damit das eingebaute `dict()`. Die Funktion könnte man auch mit `set()` lösen:

Code: Alles auswählen

        def check(self, dictionary, *keys):
            return set(keys).issubset(set(dictionary))
Das mischen von HTML und Python-Quelltext ist recht unübersichtlich. Mit dem Formatierungsoperator lässt sich das besser trennen:

Code: Alles auswählen

        def formatCmds(self, commands):
            result = list()
            for command in commands:
                result.append('<br><br><font color="FF33CC">%s >'
                              '<font color="66FF00">%s</font><br>'
                              '</font><br>%s'
                              % tuple(self.escHtml(command[attr])
                                      for attr in ('pwd', 'cmd', 'cmdResp')))
            return ''.join(result) or 'dummy'
Das Argument `port` in HTTPserver.__init__()` wird nicht benutzt. Und Namen komplett in Grossbuchstaben kennzeichnen per Konvention Konstanten. Das `SEASON` später im Quelltext verändert wird, ist recht unerwartet.

In `HTTPserver.serve()` gibt's Namen die zu kurz und nichtssagend sind und es werden `file` und `socket` verdeckt. Insgesamt gibt es zuviele Namen, Zeilen und Verzweigungen in dieser Methode. Die sollte man unbedingt aufteilen. Bei so langen und unübersichtlichen Funktionen übersieht man bei Änderungen schon mal schnell, dass eine Variable mit gleichem Namen in einem anderen ``if``-Zweig für etwas anderes verwendet wird, oder das Namen, wie in diesem Fall `weiter`, gar nicht benutzt werden. Ersteres mag für den korrekten Programmablauf kein Problem sein, verwirrt aber den Leser -- macht den Quelltext also auch schwerer zu debuggen.

Schlimm sind auch verwirrende Kommentare, wie zum Beispiel bei `weiter`, oder Kommentare die nicht mehr mit dem Quelltext übereinstimmen. Zwei Zeilen nach dem `weiter`-Kommentar ist einer, der wohl nicht mehr aktuell ist.

Ein Grund nicht selbst einen HTTP-Server zu implementieren ist, dass Socket-Programmierung recht fehleranfällig sein kann. Du liesst nur einmal etwas aus dem Socket, es ist aber absolut nicht garantiert, dass mit diesem einen Lesezugriff auch alles gelesen wird, was von der Gegenseite gesendet wurde. Das mag lokal beim Testen nie ein Problem sein, aber wenn das grosse böse Internet und Router dazwischen sind, und Pakete fragmentiert werden, verschiedene Wege durch's Netz nehmen und nicht in der richtigen Reihenfolge ankommen, dann passiert es durchaus, dass erst einmal nur ein Teil der Daten an die Anwendung weitergegeben wird.

Das `param2` kann man sich sparen:

Code: Alles auswählen

                param = dict((key, ''.join(value))
                             for key, value in cgi.parse_qs(query))
Bei ``os.popen("pwd")`` wird die Datei nicht wieder geschlossen, was zu Zombieprozessen führen kann, ausserdem gibt's `os.getcwd()`.

Die ganzen expliziten Abfragen nach Schlüsseln und das Aufrufen von `missing()` lässt sich wahrscheinlich vereinfachen, indem man einfach auf die Schlüssel zugreift und die Ausnahme entsprechend behandelt.

Du hast ja nach Techniken zur Fehlersuche gefragt: ``except`` ohne konkrete Ausnahme wie in Zeile 71 ist eine "Anti-Technik". Wenn Du Dich jetzt zum Beispiel im ``try``-Block bei einem Namen vertippt hast, dann wird ein `NameError` oder `AttributeError` ausgelöst. Den bekommst Du aber nie zu Gesicht, sondern wunderst Dich erst einmal warum `query` immer leer ist. Mit so einem "nackten" ``except`` kann man wunderbar Fehlermeldungen unterdrücken und sich den Wolf suchen wenn da ein Fehler verschluckt wird der wichtig gewesen wäre.

Mit einem ``try``-Block die (nicht)existenz eines lokalen Namens zu prüfen und ihn zu definieren falls er nicht existierte ist sehr unsauber. So einen Namen bindet man am besten an `None` und prüft das dann an der entsprechenden Stelle.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

cracki hat geschrieben:sape:
(1) wir sind hier nicht in java, weil python != java. man vergleiche die grammars. :>
(2) er missbraucht die eine klasse (utils) anscheinend als namespace
(3) fuer dieses problem sehe ich nicht, wie eigene klassen zu rechtfertigen waeren. die webserverklasse koennte er mit stdlib sachen locker ausduennen

ich bin gespannt auf morgen/heute, wenn du was zu meiner pauschalisierung (welche eigentlich?) sagen wirst.
Korrekt, warum nicht gleich so :) Siehst selber das der Satz ohne Bezug auf die Sachen die du jetzt angesprochen hast, sehr Pauschal klang. Dein Satz hat sich halt für mich so gelesen als ob man generell nicht Klassen in Python nutzen sollte weil "Python != Java". Das hast du ja jetzt ausreichende widerlegt.
Leonidas hat geschrieben:
sape hat geschrieben:Morgen schreibe ich zu dieser Pauschalisierung was! -> Also ich liefere auch eine Begründung dazu und stelle nicht pauschal ein nicht haltbare Behauptung auf.
An dieser Stelle ist es nicht pauschal. Wie ich schon geschrieben habe, ist die Utils-Klasse vällig sinnentleer. Für sowas erstellt man ein Modul utils.py und fertig.

Kann mir jemand sagen, was dieser Code überhaupt machen soll?
Hab dich auch nicht gemeint :) Deine Begründung war schlüssig (und auch deine jetzige die sogar ausführlicher ist) und daher völlig i.O.


...

Vielleicht sollte man sich generell angewöhnen nicht eine Satz wie "und lass die klassen weg, wir sind hier nicht in java." in den Raum zu schmeißen. Der liest sich halt so "einseitig" und Anfänger könnte auf die Dumme Idee kommen und das sogar glauben und aufgrund dessen keine Klassen Schreiben, was einer der grössten Fehler wäre dies nicht zu nutzen ;)

Ich hoffe meine Intention sollte nun klar sein.

lg

P.S.: Ich wäre dafür ins Wiki aufzunehmen wann es Sinn macht Klassen zu schrieben und wann nicht.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

sape hat geschrieben:Vielleicht sollte man sich generell angewöhnen nicht eine Satz wie "und lass die klassen weg, wir sind hier nicht in java." in den Raum zu schmeißen. Der liest sich halt so "einseitig" und Anfänger könnte auf die Dumme Idee kommen und das sogar glauben und aufgrund dessen keine Klassen Schreiben, was einer der grössten Fehler wäre dies nicht zu nutzen ;)
Klar, etwas einseitig ist es schon, aber Leute die von java kommen, tendieren alles aufs biegen und brechen in Klassen zu packen, so wie sie Java trainiert hat. Daher ist der Generelle AUsspruch Python ist nicht Java durchaus korrekt. Er bezeichnet nämlich nicht nur dass man sich nicht zu OOP zwingen sollte, sondern auch eine reihe Anderer Dinge, die PJE im Python is not Java aufzeigt.
sape hat geschrieben:P.S.: Ich wäre dafür ins Wiki aufzunehmen wann es Sinn macht Klassen zu schrieben und wann nicht.
Bitte, nur zu. MoinMaster funktioniert inzwischen wieder und man kann wieder Seiten editieren. Vielleicht wäre es sogar gut, PJEs eintrag mehr oder weniger zu übersetzen und zu erweitern, denn das was er dort schreibt hat durchaus Hand und Fuß.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

sape hat geschrieben:P.S.: Ich wäre dafür ins Wiki aufzunehmen wann es Sinn macht Klassen zu schrieben und wann nicht.
Bitte, nur zu. MoinMaster funktioniert inzwischen wieder und man kann wieder Seiten editieren. Vielleicht wäre es sogar gut, PJEs eintrag mehr oder weniger zu übersetzen und zu erweitern, denn das was er dort schreibt hat durchaus Hand und Fuß.
Hab versucht PEP8 zu übersetzten und dann hier par Sammelthreads mit übersetzten PEPs zu starten, dass ich dann aber gleich über bord geworfen habe, da mein englisch viel zu schlecht ist...Mit einer übersetzung vom "PJEs" kannst du daher von meiner Seite aus nicht rechnen.
Ansonsten bin ich gerne bereit dazu beizutragen.

lg
Costi
User
Beiträge: 545
Registriert: Donnerstag 17. August 2006, 14:21

vielen dank fuer die muehe, ich werde mir die genannten punkte anschauen

(hab jety computer verbottt *WOOOOT*) :x :oops:
cp != mv
Antworten