Seite 1 von 2

pyChat

Verfasst: Freitag 26. Februar 2010, 21:53
von weißned
Hey Leute,

ich hab in den letzten 3 Tagen mal versucht einen ganz simplen Chat zu schreiben :D


Ich hoffe ein Profi kann sich das ganze mal ansehn und mir sagen was ich falsch mache bzw. man besser machen kann.

Danke euch

Download: http://drop.io/thepychat

Verfasst: Freitag 26. Februar 2010, 22:10
von derdon
Achte auf PEP8 (z.B. Klassennamen in CamelCase, EOL79). Bei console_client.py auf die Einrückung achten (nach ``while True:`` sollte wohl eingerückt werden). gui_client.py: Zeile 84 kann man so ersetzen:

Code: Alles auswählen

>>> from functools import partial
>>> from operator import eq
>>> ip, name, port = '127.0.0.1', '', '80'
>>> is_empty_string = partial(eq, '')
>>> any(is_empty_string(entry) for entry in (ip, name, port))
True
Das ist zwar länger und für Anfänger unleserlich, aber dafür cooler 8)


Insgesamt sieht es aber nach gutem Code aus (weniger als Minute raufgeschaut).

Verfasst: Samstag 27. Februar 2010, 22:11
von weißned
Hey, danke schon mal dafür, die PEP8 werde ich mir nochmal genauer ansehn, und Zeile 84 werde ich so ersetzten.

Hat sonst noch jemand was anzumerken=?

Verfasst: Samstag 27. Februar 2010, 23:32
von cofi
Wenn du es leichter verfuegbar machen kannst als ein `zip` wirst du mehr Rueckmeldungen bekommen.

Aber wenigstens ist es kein `rar` ...

Verfasst: Samstag 27. Februar 2010, 23:35
von Leonidas
Hallo weißned, willkommen im Forum,
weißned hat geschrieben:Hat sonst noch jemand was anzumerken=?
Ja. Das die Module nach Klassen aufgeteilt sind macht in meinen Augen wenig Sinn, eine thematische Ordnung fände ich besser. Auch client.py und clients.py finde ich - verwirrend, zudem clients.py eine ziemlich sinnlose Klasse ist (Python hat Properties - keine Getter und Setter nötig, die zudem nichts tun). Ich würde auch viel weniger String-Konkatenation nutzen, mehr String-Formatting um Daten anzupassen. Da spart man sich auch das wrappen von Kram in ``str()`` und es ist klarer was dargestellt werden soll. Achja, ``input`` ist eine eingebaute Funktion, die überschreibst du an irgendeiner Stelle - sollte man besser nicht machen.

Ich has mir nicht im Detail angeschaut aber ansonsten sehe ich keine weiteren offensichtlichen WTFs, insofern kann ich mich derdon anschließen dass der Code insgesamt recht gelungen scheint. Was ich dir aber empfehlen könnte wäre ein Blick in asyncore, speziell asynchat scheint ziemlich gut zu deinem Problem zu passen.

cofi, naja ZIP sehe ich zwar nicht so gerne wie Tarballs, aber es ist IMHO ein brauchbarer Kompromiss der für die meisten Platformen annehmbar ist. Und drop.io ist zum runterladen noch annehmbar, nicht so wie gewisse, im folgenden ungenannte Filehoster. Ein Upload auf Bitbucket/Github wäre natürlich der logische nächste Schritt ;)

Verfasst: Sonntag 28. Februar 2010, 16:58
von weißned
Hey ich habs jetzt geschafft ein bitbucket repo zu machen, bloß wenn ich auf Source kilcke steht dort, dass keine Dateien da sind aber ich habe sie hoch geladen.

Wenn ich eine Revision anklicke sehe ich die ja auch, hat jemand ne Ahnung wie man das machen kann den Source Code anzuzeigen ohne eine bestimmte Revision anzuklicken müssen?

naja also hier der Code: http://bitbucket.org/mjdv/thepychat/src/tip

@Leonidas ich habe die Klasse clients jetzt in server.py getan, aber ich glaube ich brauche diese Klasse doch, es sind nämlich nicht nur getter und setter enthalten!

edit:

Wegen dem input, überschreibe ich die input Funktion auch wenn ich eine Varible input habe?

Verfasst: Sonntag 28. Februar 2010, 17:16
von Leonidas
weißned hat geschrieben:Wenn ich eine Revision anklicke sehe ich die ja auch, hat jemand ne Ahnung wie man das machen kann den Source Code anzuzeigen ohne eine bestimmte Revision anzuklicken müssen?
Du kannst den Hash in der URL durch "tip" ersetzen, dann zeigt es auf die aktuellste Revision.
weißned hat geschrieben:Wegen dem input, überschreibe ich die input Funktion auch wenn ich eine Varible input habe?
Ja, denn Python ist ein Lisp-1^W^W eine Sprache mit nur einem Namespace indem sowohl Funktionen als auch sonstige Namen sind. Variablen hat Python an sich nicht.

Verfasst: Sonntag 28. Februar 2010, 17:27
von weißned
Leonidas hat geschrieben:
weißned hat geschrieben:Wenn ich eine Revision anklicke sehe ich die ja auch, hat jemand ne Ahnung wie man das machen kann den Source Code anzuzeigen ohne eine bestimmte Revision anzuklicken müssen?
Du kannst den Hash in der URL durch "tip" ersetzen, dann zeigt es auf die aktuellste Revision.
Okay, kann man das auch machen wenn man so auf den Source Button klickt oder muss immer eine Revision ausgewählt sein?

Verfasst: Sonntag 28. Februar 2010, 17:28
von lunar
derdon hat geschrieben:

Code: Alles auswählen

>>> from functools import partial
>>> from operator import eq
>>> ip, name, port = '127.0.0.1', '', '80'
>>> is_empty_string = partial(eq, '')
>>> any(is_empty_string(entry) for entry in (ip, name, port))
True
Mein Gott …

Code: Alles auswählen

any(not entry for entry in (ip, name, port))
Edit: @weißned: Wenn eine bestimmte Revision im Link steht, auf "Overview" klicken, anschließend wieder auf "Source" und dann die Datei auswählen. Dann zeigt der Link auf "tip" … ist etwas unintuitiv, aber wenigstens funktionierts.

Verfasst: Sonntag 28. Februar 2010, 17:46
von Leonidas
Ich hab dir mal einen pull-Request mit meinen Änderungen geschickt...

Außerdem, was mir aufgefallen ist: du handhabst Fehler durch leere Strings! Dafür gibt es Exceptions, die sollte man auch nutzen. So kann es vorkommen dass man vergisst irgenwelche Fehler abzufangen und dann kracht es an unerwarteten Stellen.

Verfasst: Sonntag 28. Februar 2010, 17:58
von weißned
@Leoniads

Das ist echt nett, danke, aber wie nehme ich den an? Oo

Verfasst: Sonntag 28. Februar 2010, 18:12
von cofi
Indem du von seinem Repository pullst ;)

`hg pull $repository`
und dann eben pushen ;)

Verfasst: Sonntag 28. Februar 2010, 18:15
von weißned
Oh okay danke, ich dachte da gibst ne Funktion wo ich dann ja sagen muss, dass ich die Änderungen in mein Repo übernehmen will xD

Danke

edit:
Das mit den leeren Strings stimmt schon ist ein wenig doof, aber wir könnt ich es denn anders lösen? Soll ich dann selber eine Exception auslösen?

Verfasst: Sonntag 28. Februar 2010, 18:30
von Leonidas
weißned hat geschrieben:Das mit den leeren Strings stimmt schon ist ein wenig doof, aber wir könnt ich es denn anders lösen? Soll ich dann selber eine Exception auslösen?
Ja. Du kannst ja auch eigene Exceptions definieren.

Verfasst: Sonntag 28. Februar 2010, 18:50
von weißned
Also zum Beispiel:

Code: Alles auswählen

try:
    c.send(message)
except Exception as ex:
    raise MyError('error sending message!\nDetails: %s\n%s' %(type(ex), ex)
Wäre das okay so?

Verfasst: Sonntag 28. Februar 2010, 19:07
von cofi
Ja. In Ordnung ist das aber nur, wenn du den Typ nicht genauer weisst (und selbst dann ist `except BaseException` zu bevorzugen).

Verfasst: Sonntag 28. Februar 2010, 19:54
von Leonidas
Statt dem except Exception würde ich eher die spezifische Exception abfangen. Sonst verschluckst du gegebenfalls irgendwelche wirklich unerwarteten Ausnahmefälle.

Verfasst: Sonntag 28. Februar 2010, 20:10
von weißned
Naja ich möchte aber das jede beliebige Exception abgefangen wird, also zum Beispiel auch wenn man für Port keine Zahl eingegeben hat.

Verfasst: Sonntag 28. Februar 2010, 20:11
von cofi
cofi hat geschrieben:In Ordnung ist das aber nur, wenn du den Typ nicht genauer weisst (und selbst dann ist `except BaseException` zu bevorzugen).

Verfasst: Sonntag 28. Februar 2010, 20:21
von /me
weißned hat geschrieben:Naja ich möchte aber das jede beliebige Exception abgefangen wird, also zum Beispiel auch wenn man für Port keine Zahl eingegeben hat.
... oder wenn ein Syntaxfehler im Code ist oder wenn der User das Programm beenden möchte ...