Anfängerfrage: Problem mit Chatprogramm in Python

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
sinnaj-r
User
Beiträge: 1
Registriert: Dienstag 8. Januar 2013, 19:42

Zu erst möchte ich erstmal sagen das dies meine erster Post in diesem Forum ist (bzw. ich recht neu in Python bin) und deswegen , sollte ich was falsch machen , weisst mich darauf hin ich lerne aus Fehlern.
So nun zu meinem Problem:
Ich habe eine kleines Local-Network-Chatprogramm entwickelt, bei dem man zwischen zwei Clients hin und her chatten kann.
Und da liegt auch gleich der Hase im Pfeffer begraben da momentan nur Client 2 senden kann und Client 1 entweder nicht senden oder Client 2 nicht empfangen kann(eine Fehlermeldung oder ähnliches wird garnicht erst ausgegeben).
Ich würde mich freuen wenn ihr euch das Programm mal anschauen könntet da ich nun schon seit ewigkeiten an dem Problem arbeite(Habe auch schon meine Informatik Lehrerin um hilfe gebeten) konnte aber noch keine Lösung finden.
Hier der Code:
https://gist.github.com/46964c3446fdd7a4033f
BlackJack

@sinnaj-r: ``global`` auf Modulebene ist sinnfrei — das hat dort keinen Effekt. Grundsätzlich sollte man ``global`` vermeiden, da das unsaubere Programme mit undurchsichtigen Abhängigkeiten zwischen Funktionen zur Folge hat. Es sind ausserdem total unsinnige ``gobal``-Deklarationen dabei — welche die gar nicht verwendet werden oder der Name der Funktion selbst.

Wo hast Du denn die Syntax mit den Backticks in der `key()`-Funktion her? Die benutzt man nicht. Wer zu faul ist die `repr()`-Funktion auszuschreiben, sollte besser die Finger von Python lassen und Perl verwenden. ;-)

Die Anwendung ist hier aber auch unsinnig, denn statt einem Vergleich der `repr()`-Darstellung des Zeichens mit einer literalen `repr()`-Darstellung hätte man auch das Zeichen direkt mit einer normalen Darstellung vergleichen können.

``if`` ist keine Funktion, also sollte man es auch nicht so schreiben als wäre es eine. Die Klammern um die Bedingung sind in Python überflüssig → weg lassen.

Die Namensschreibweise hält sich nicht an den Style Guide for Python Code. Auch sollte man Namen nicht ohne Not abkürzen. `abse` und `nachr`? Was soll das? Sind die Buchstaben knapp geworden? Wenn man `absender` und `nachricht` meint, sollte man das auch schreiben. Namen sollen dem Leser klar vermitteln wofür die Werte dahinter im Programmkontext stehen. Und nicht zum Rätselraten anregen oder gar zwingen.

Statt `str()` und ``+``, was nach BASIC aussieht, verwendet man in Python Zeichenkettenformatierung mit der `format()`-Methode auf Zeichenketten oder dem ``%``-Operator.

``del`` ist fast so selten sinnvoll wie ``global``. In Deinem Programm macht es jedenfalls keinen Sinn → weg lassen.

Ein nacktes ``except:`` ohne konkrete Ausnahme(n) ist keine gute Idee. Du behandelst da Ausnahmen in einer Weise die nicht sinnvoll ist. Es erschwert ausserdem die Fehlersuche. Wenn Du Dich im ``try``-Block in `send()` zum Beispiel irgendwo bei einem (Attribut)Namen vertippt hast, bekommst Du keinen `NameError` oder `AttributeError` der Dich genau zu der fehlerhaften Zeile führt, sondern Dein Programm gibt die wenig hilfreiche Meldung aus, dass Umlaute nicht erlaubt sind.

Das `thread`-Modul ist veraltet und schon seit 10 Jahren vom `threading`-Modul abgelöst. Ausserdem vertragen sich GUIs und Threads nur unter bestimmten Bedingungen. Die `tk`-GUI darf nur aus dem Thread heraus verändert werden, in dem auch die `mainloop()` läuft. Kommunikation zwischen Threads löst man in der Regel mit `Queue.Queue`-Objekten und der `after()`-Methode auf `Tkinter`-Widgets.

Du hast Dir da ein Projekt vorgenommen was so ziemlich alle komplizierten Sachen auf einmal in sich vereint, und das bevor Du die Grundlagen richtig beherrschst. Direkte Socketprogrammierung ist nicht einfach und birgt so einige Fallstricke. Das gleiche gilt für Threads. Bevor man mit GUI-Programmierung anfängt, sollte man objektorientierte Programmierung (OOP) halbwegs können. Bevor man mit OOP anfängt, sollte man Funktionen richtig verwenden können. Also keine ``global``-Anweisungen die Funktionen zu Codeschnippseln mit Namen degradieren. Da ist man dann schon fast wieder bei den Anfängen von BASIC.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@sinnaj-r: wie BlackJack schon geschrieben hat, sind threads und GUI mit größter Vorsicht zu betreiben.
Die Funktion enter als Thread auszuführen macht überhaupt keinen Sinn, da dort
nur callbacks gebunden werden.
Sockets sind bidirektional, das heißt, man kann über den selben Socket sowohl
empfangen als auch senden. Für jede Nachricht einen neuen Socket zu erzeugen
(vor allem auf der Empfängerseite) ist zumindest unnötiger Overhead, das System
kann mit dem ständigen Zuweisen auf den selben Port irgendwann
durcheinanderkommen und Nachrichten verlorengehen.

Einfachstes Vorgehen:
Keine Threads. Ein nonblocking Socket auf der Empfängerseite der mit after regelmäßig auf neue Nachrichten geprüft wird.
Antworten