was fuer endbuging methoden gibt es eigentlich noch, auser alle wichtige variablen zu printen
danke
debugging methoden
-
- 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
Den Quelltext so zu schreiben, dass man im Interpretierer die einzelnen Funktionen "live" ausprobieren kann und Unit-Tests helfen auch.
-
- 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.
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
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?
bug fixed ( ; (lag nicht nur an "{"cmd": "dummy0", "cmdResp": "dummy1", "cmd": "dummy2"}")
wie wuerdest es du den ungefaehr schreieben?
cp != mv
wow schreib den code neu!
erster tipp:
und lass die klassen weg, wir sind hier nicht in java.
erster tipp:
Code: Alles auswählen
somedict.has_key(key) == (key in somedict)
...meh...
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 hat geschrieben:[...]
und lass die klassen weg, wir sind hier nicht in java.
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.
(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...
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
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.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.
Kann mir jemand sagen, was dieser Code überhaupt machen soll?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
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:
Das mischen von HTML und Python-Quelltext ist recht unübersichtlich. Mit dem Formatierungsoperator lässt sich das besser trennen:
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:
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.
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))
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'
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))
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.
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.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.
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.Leonidas hat geschrieben: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.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.
Kann mir jemand sagen, was dieser Code überhaupt machen soll?
...
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.
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
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: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
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ß.sape hat geschrieben:P.S.: Ich wäre dafür ins Wiki aufzunehmen wann es Sinn macht Klassen zu schrieben und wann nicht.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
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.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ß.sape hat geschrieben:P.S.: Ich wäre dafür ins Wiki aufzunehmen wann es Sinn macht Klassen zu schrieben und wann nicht.
Ansonsten bin ich gerne bereit dazu beizutragen.
lg