[Gelöst]Python Backgrounding (GTK) - asyncore.loop() beenden

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.
maxi_king_333
User
Beiträge: 110
Registriert: Freitag 25. Dezember 2009, 03:42

Hi,

bin mir nicht sicher ob das hier richtig ist, aber ich denke schon.
Und zwar habe ich ein Problem.
Ich möchte eine Art Monitor schreiben, der im Hintergrund auf Informationen über einen Socket wartet.
Nun zum eigentlichen Problem, ich habe eine dauerhafte Funktion laufen, in meinem Fall ist das gtk.main().
Nun kann ich ja während diese Funktion läuft nichts anderes tun.
Nun ist meine Idee eine Art Background Funktion zu haben, die das Ankommende entgegen nimmt, auswertet und dann einer Funktion übergibt, die es dann z.B. in GTK sichtbar macht oder auf dem Bildschirm ausgibt.
Wie das mit dem Socket und so geht ist jetzt erstmal egal.
Bitte einfach nur ein einfaches Beispiel was einfach nur alle 5 Sekunden Hallo Welt ausgibt oder so.

/* Edit: So, nachdem ich mich hier ein wenig rumgeklickt habe bin ich auf http://www.python-forum.de/topic-21225.html gestoßen.
Das macht eigentlich genau das, was ich will. */

Vielen Dank schonmal fürs Lesen und Viele Grüße
Maxi[/url]
Zuletzt geändert von maxi_king_333 am Montag 4. Januar 2010, 13:18, insgesamt 3-mal geändert.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Dazu kannst du einen Timer verwenden (threading.Timer), ich weiß nicht wies mit GTK aussieht, wxPython hat einen Timer (wx.Timer), vorzugsweise würde ich dann den Timer von GTK benutzen,
oder du verwendest threads [mod]threading[/mod], so wie in deinem Link
the more they change the more they stay the same
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

maxi_king_333
User
Beiträge: 110
Registriert: Freitag 25. Dezember 2009, 03:42

Hi,

Vielen Dank für Eure Hilfe.
Mir ist nun aufgefallen, dass GTK auch eine Ausgabe bringt ohne die gtk.main() aufzurufen.
Also weg damit.

Nun hänge ich bei asyncore.loop() fest, denn dieses muss aufgerufen werden. Nur ich weiß im Moment noch nicht, wie ich es wieder beenden kann.
Ich habe es schon in einen Thread verschoben und das funktioniert auch.
Nur beenden kann ich es nicht.
Zu meinem Code:
Habe eine Klasse mit den Funktionen und auch eine Close Funktion.
Diese wird auch aufgerufen und zerstört das Socket.
Nur der Loop läuft einfach weiter.

Weiß einer hier, wie asyncore.loop() beenden kann?

Viele Grüße
Maxi
BlackJack

Den `gtk.main()`-Aufruf wegzulassen ist keine gute Idee, es sei denn *Du* treibst die Hauptschleife von Gtk irgendwo an. Dass es *bei Dir* auch ohne diesen Aufruf zu funktionieren scheint, ist keine Garantie, dass das *grundsätzlich* geht.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

du musst keine asyncore.loop aufrufen

du kannst stattdessen asyncore.poll alle 0.2s, 0.5s oder weniger oder mehr je nach dem aufrufen, asyncore.loop macht im Grunde genau das, das kannst du mit einem Timer machen oder einem Thread (Timer wäre einfacher und besser)
the more they change the more they stay the same
maxi_king_333
User
Beiträge: 110
Registriert: Freitag 25. Dezember 2009, 03:42

Hi,
Den `gtk.main()`-Aufruf wegzulassen ist keine gute Idee, es sei denn *Du* treibst die Hauptschleife von Gtk irgendwo an. Dass es *bei Dir* auch ohne diesen Aufruf zu funktionieren scheint, ist keine Garantie, dass das *grundsätzlich* geht.
Okay, das wusste ich nicht - Vielen Dank.
du musst keine asyncore.loop aufrufen

du kannst stattdessen asyncore.poll alle 0.2s, 0.5s oder weniger oder mehr je nach dem aufrufen, asyncore.loop macht im Grunde genau das, das kannst du mit einem Timer machen oder einem Thread (Timer wäre einfacher und besser)
Sollte ich generell lieber einen Timer nehmen?
Habe es nämlich so gelöst, dass von meinem asyncore.dispatcher die Daten in ein Queue geschoben werden, was wiederum von einem Thread in einer unendlichen while ausgelesen und der Reihe nach verarbeitet wird. Dieser Thread startet bis zu 20 neue Threads die wiederum Informationen verarbeiten. Und jetzt könnte ich den doch einfach jede Sekunde anwerfen und das Queue auslesen lassen. Wäre das nicht Ressourcen sparender als die while Schleife?

Es geht in der Anwendung darum, dass erst eine Status Meldung von einem Server kommt, diese wird verarbeitet und dann z.B. eine Meldung auszugeben.
Dann sollen aber quasi gleichzeitig verschiedene Aktionen ausgeführt werden z.B. Musik stoppen und über lib-notify eine Meldung bringen.
Da diese Aktionen von dem User bestimmt werden sollen, kann ich das nicht einfach irgendwie aneinander hängen.
Der User hat dann viele Möglichkeiten, was wie und wann ausgeführt werden soll.
Bei dem Server handelt es sich um einen AVM Call Monitor Server.

Viele Grüße
Maxi
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Du könntest das "Informationen kriegen" und das "Informationen verarbeiten" zusammen "schmeisen" und die Funktion mit einem Timer aufrufen, allerdings musst du das in der Klasse machen die von asyncore.dispatcher erbt (wegen den Events!)
the more they change the more they stay the same
maxi_king_333
User
Beiträge: 110
Registriert: Freitag 25. Dezember 2009, 03:42

So ganz bin ich mit meiner bisherigen Struktur auch nicht zufrieden, da ich haufenweise Variablen habe, die die Verschiedenen Notify Stufen halten.
Diese Variablen müssen auch irgendwann gelöscht werden.
Am besten durch das Objekt dem sie zugeordnet sind.

Das verarbeiten und das Informationen bekommen könnte ich schon durch eine Funktion erledigen, was zum Teil auch schon passiert.
Die extra verarbeiten Funktion speichert nur, welcher Verbindung was zugeordnet ist.
Und dieses Speichern ist wiederum nötig, da vom AVM Anruf Monitor nicht immer alles übermittelt wird.

Beispiel: Jemand ruft an.
Nun wird das Event RING ausgelöst.
Die Nummer des Anrufers, die angerufene Nummer und eine Instanz Nummer wird übermittelt.
Nun speichere ich unter der Instanz Nummer all diese Daten.
Jetzt wird das Event CONNECT ausgelöst, weil jemand herangegangen ist.
Nun wird aber nur die Instanz Nummer und das Gerät, von dem aus angenommen wurde übermittelt.
Anhand der Instanz Nummer kann ich nun aber durch die Speicherung auch alle anderen Daten abfragen.
Jetzt wird aufgelegt und das Event DISCONNECT ausgelöst.
Nun wird die gespeicherte Instanz gelöscht.

Bei jedem dieser Events werden weitere Events aufgerufen, also z.B. halte die Musik an.
Diese werden aber durch ein für jede Instanz Nummer erzeugtes Objekt aufgerufen, das als Thread läuft.
Nun habe ich aber das Problem, sollte die Instanz Nummer erneut vergeben werden, die Events aber noch nicht fertig sein.
Dann funktioniert das nicht.
Deshalb erzeuge ich die Events aus einem Objekt, was eine Thread ist und einer zufälligen Variable zugeordnet ist.
Diese Variable muss ich nun löschen, doch wie?

/* Edit: Ich glaube ich muss mein Konzept nochmal überarbeiten.
Werde dann hier bei weiteren Fragen auch den Code dazu tun.
Nur im Moment sitze ich nicht an dem Rechner, wo der Code drauf ist. */

Viele Grüße
Maxi
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Deshalb erzeuge ich die Events aus einem Objekt, was eine Thread ist und einer zufälligen Variable zugeordnet ist.
Diese Variable muss ich nun löschen, doch wie?
Wie diese Variabeln erzeugst möchte ich lieber gar nicht wissen, (eval, exec), verwende lieber dicts als Key kannst du z.B. auch eine Instanz einer Klasse benutzen!
the more they change the more they stay the same
maxi_king_333
User
Beiträge: 110
Registriert: Freitag 25. Dezember 2009, 03:42

Hi,
Wie diese Variabeln erzeugst möchte ich lieber gar nicht wissen, (eval, exec), verwende lieber dicts als Key kannst du z.B. auch eine Instanz einer Klasse benutzen!
Bis jetzt habe ich:

Code: Alles auswählen

self.EventHandle[randomid]=EventHandle(infos)
self.EventHandle[randomid].start()
Benutzte ich die so nicht?
Naja, jedenfalls sollte "self.EventHandle[randomid]" nach Beendigung von "EventHandle.run()" gelöscht werden.

/* Edit: Achja, nicht dass irgendwer denkt ich hätte mir diesen Code jetzt schnell aus der Antwort ausgedacht.
Der ist schon die ganze Zeit so.
Bin zwar noch ein Anfänger aber das kenne ich von PHP und habe es deshalb auch direkt verwendet.
Wobei ich am Anfang nach Assoziatives Array gesucht habe ;).
Für jedes eine richtige Variable zu machen wäre Schwachsinn */

Viele Grüße
Maxi
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Gut du verwendest dicts

Ich würde jetzt randomid durch eine Instanz einer Klasse austauschen, ich kenne deinen Code jetzt nicht
So ganz bin ich mit meiner bisherigen Struktur auch nicht zufrieden, da ich haufenweise Variablen habe, die die Verschiedenen Notify Stufen halten.
Diese Variablen müssen auch irgendwann gelöscht werden.
Am besten durch das Objekt dem sie zugeordnet sind.
Z.B. das "Objekt" als Schlüssel für das dict
the more they change the more they stay the same
maxi_king_333
User
Beiträge: 110
Registriert: Freitag 25. Dezember 2009, 03:42

Hi,

erstmal ein frohes Neues und viel Glück und Gesundheit.

Ich glaube ich brauche nochmal einen kleinen Denkanstoß (fertigen Code will ich garnicht, nur wie ich das mit den Objekten als Key hinbekomme bzw. wie sich die Objekte automatisch löschen bzw. wie ich das mit den Zufallszahlen geschickter löse).
Hier ist mein Code: http://bazaar.launchpad.net/~maxi-morit ... runk/files
Ja, es ist bereits ein Projekt, wobei ich zu BerliOS umziehen möchte.
Mag seltsam sein, mit einem Projekt zu lernen, doch ich brauche ein Projekt, sonst lerne ich nichts bzw. verliert nach ein paar Stunden wieder die Lust.
Für Benutzter der AVM FritzBox und Linux ist das bestimmt interessant.

/* Edit: Achja, vielleicht sollte ich noch sagen, was die Dateien machen.
  • fbcallnotify.py - Main-Datei, startet alles.
  • callmonitor.py - Überwacht das Netzwerk.
  • parse.py (um die geht es, da mache ich das mit den Zufallszahlen) - Verarbeitet die Informationen und startet notifyer(notifyer.py) Threads welche wiederum notify(notify.py) Events auslösen
Ich weiß, dass Ihr das schlecht ohne FritzBox testen könnt, ich hoffe, ihr könnt mir dennoch helfen.*/

Viele Grüße
Maxi
BlackJack

@maxi_king_333: Wenn man sich erst einmal an den Style Guide gewöhnt hat, und auch daran, dass den die meisten anderen auch befolgen, dann fällt es immer unangenehm auf, wenn jemand das nicht tut. Tabs statt Leerzeichen zum Einrücken, keine Leerzeichen um Operatoren und nach Kommas, kleingeschriebene Klassennamen -- da könntest Du mal was dran ändern.

Wenn Du dauernd Sternchen beim Importieren benutzt, kanns Du auch gleich alles in eine Datei schreiben! Vielleicht ist Dir ja gar nicht bewusst, dass Du in `fbcallnotify` all das hier unnütz importierst: `string`, `random`, `notify`, `socket`, `notifyer`, `threading`, `os`, und `notify_thread`. `sys` wird explizit importiert, aber auch nicht verwendet.

Die Funktionen aus dem `string`-Modul, die es auch als Methoden auf Zeichenketten gibt, sollte man nicht mehr verwenden. Das betrifft `callmonitor.handle_read()`. Das was da steht könnte man mit "list comprehensions" bzw. einem Generatorausdruck kompakter schreiben:

Code: Alles auswählen

    def handle_read(self):
        for info in (s.split(';') for s in self.recv(8192).split('\n')):
            if info and info[0]:
                self.pool.put(info[:-1])
Wobei ich mir nicht sicher bin, ob immer garantiert ist, dass man bei dem `recv()`-Aufruf Datenblöcke ganze Zeilen bekommt, und nicht auch mal eine Zeile über zwei `recv()`-Aufrufe verteilt sein kann!? Das sollte man klären.

Kommen wir zur `genrandomid()` -- die sowohl in `parse` als auch in `notifyer` definiert ist und in beiden Fällen in einer Klasse steckt, ohne auf diese wirklich angewiesen zu sein. Das ist also eine Funktion und keine Methode und könnte irgendwo extra definiert werden, wenn sie von verschiedenen Stellen aus verwendet wird.

Zum Inhalt der Funktion: Was soll das? Zwei Zufallswerte aus dem gleichen Bereich erst in ein Dictionary stecken um sie dann zu addieren!? Das ist eine sehr umständliche Art ``random.randint(10000, 99999) + random.randint(10000, 99999)`` zu schreiben. Bleibt immer noch die Frage warum Du absichtlich "schlechte" Zufallszahlen erzeugst, denn die sind durch die Addition ja nicht mehr gleichverteilt.

Und dann habe ich echt nicht verstanden was Du da eigentlich machen willst. Du hast `notifyier`-Objekte, die als Thread laufen um dann ihrerseits noch einmal jeweils einen Thread zu starten!? Warum das? Die haben ein Dictionary namens `notify` welches immer nur zwei ein Elemente enthält -- wenn man wegen der Zufallszahlen kein Pech hat. Was soll das Dictionary und warum steckst Du da Objekte rein? Warum mit Zufallszahlen als Schlüssel? Das gleiche gilt für `parse` -- warum das `notifyer`-Dictionary? Du greifst bei beiden nie wieder auf die Daten zu.

Was ist der Sinn der `notify`-Objekte? Das könnte eine Funktion sein, aber doch keine Klasse.

Die `Queue` würde ich übrigens nicht `pool` nennen, das ist von der Semantik her eine Jobqueue und kein Pool von Ressourcen, was man bei dem Namen `pool` eher erwarten würde.

Die `parse.run()` könnte man etwas mehr OOP gestalten. Zum Beispiel in dem man dynamisch `handle`-Methoden auf `parse`-Exemplaren aufruft, je nach Inhalt von ``info[2]``, was man auch an einen sprechenden Namen binden könnte, und die Werte im `connections`-Dictionary könnte man auch als Objekte modellieren.

In Zeile 52 gibt's übrigens ein Problem mit `indo` was wohl `info` heissen sollte.
maxi_king_333
User
Beiträge: 110
Registriert: Freitag 25. Dezember 2009, 03:42

Hi,

schonmal Vielen Dank für Deine Antwort.
@maxi_king_333: Wenn man sich erst einmal an den Style Guide gewöhnt hat, und auch daran, dass den die meisten anderen auch befolgen, dann fällt es immer unangenehm auf, wenn jemand das nicht tut. Tabs statt Leerzeichen zum Einrücken, keine Leerzeichen um Operatoren und nach Kommas, kleingeschriebene Klassennamen -- da könntest Du mal was dran ändern
Laut PEP8 darf ich auch Tabs benutzen.
Ich mag die lieber, da ich die einfacher wieder wegbekomme.
Die Klasse os oder sys werden auch klein geschrieben, ich bin mir noch nicht so ganz klar darüber, warum die unbedingt groß sein müssen.
Mit den Operatoren naja, irgendwie finde ich das seltsam, wenn da Leerzeichen drin sind.
Werde aber trotzdem alles bis auf die Tabs ändern.
Wenn Du dauernd Sternchen beim Importieren benutzt, kanns Du auch gleich alles in eine Datei schreiben! Vielleicht ist Dir ja gar nicht bewusst, dass Du in `fbcallnotify` all das hier unnütz importierst: `string`, `random`, `notify`, `socket`, `notifyer`, `threading`, `os`, und `notify_thread`. `sys` wird explizit importiert, aber auch nicht verwendet.
Tue ich das?
War mir echt nicht bewusst, wird geändert.
Wobei ich mir nicht sicher bin, ob immer garantiert ist, dass man bei dem `recv()`-Aufruf Datenblöcke ganze Zeilen bekommt, und nicht auch mal eine Zeile über zwei `recv()`-Aufrufe verteilt sein kann!? Das sollte man klären.
Die FritzBox versendet die eigentlich so.
Also da kommen auch manchmal 2 Zeilen an, deshalb trenne ich die ja.
Kommen wir zur `genrandomid()` -- die sowohl in `parse` als auch in `notifyer` definiert ist und in beiden Fällen in einer Klasse steckt, ohne auf diese wirklich angewiesen zu sein. Das ist also eine Funktion und keine Methode und könnte irgendwo extra definiert werden, wenn sie von verschiedenen Stellen aus verwendet wird.
Mach ich...
Zum Inhalt der Funktion: Was soll das? Zwei Zufallswerte aus dem gleichen Bereich erst in ein Dictionary stecken um sie dann zu addieren!? Das ist eine sehr umständliche Art ``random.randint(10000, 99999) + random.randint(10000, 99999)`` zu schreiben. Bleibt immer noch die Frage warum Du absichtlich "schlechte" Zufallszahlen erzeugst, denn die sind durch die Addition ja nicht mehr gleichverteilt.
Tja, ich dachte eigentlich die würde er aneinander hängen.
Ich erzeuge 2, da ich irgendwie mit nur einer keine 10 Stelligen Zahlen hinbekomme.
Und dann habe ich echt nicht verstanden was Du da eigentlich machen willst. Du hast `notifyier`-Objekte, die als Thread laufen um dann ihrerseits noch einmal jeweils einen Thread zu starten!? Warum das? Die haben ein Dictionary namens `notify` welches immer nur zwei ein Elemente enthält -- wenn man wegen der Zufallszahlen kein Pech hat. Was soll das Dictionary und warum steckst Du da Objekte rein? Warum mit Zufallszahlen als Schlüssel? Das gleiche gilt für `parse` -- warum das `notifyer`-Dictionary? Du greifst bei beiden nie wieder auf die Daten zu.
Im Moment erscheint es Sinnlos, aber da später der User verschiedene Notify Events festlegen können soll, die dann entweder einfach gestartet werden oder gewartet wird, bis sie fertig sind.
Deshalb die Klassen notify und notify_thread.
Da sollen später noch Dinge rein wie: "Auf der Shell ausführen" oder "Notify über Libnotify".
Die Klasse Notifyer liest später die Konfiguration ein und führt danach dann die Notify Events aus.
Da es sich um einen Anrufmonitor handelt und da auch mal ein ausgehender und ein ankommender Anruf gleichzeitig kommen können, muss der Notifyer ein Thread sein, damit ich quasi gleichzeitig eine Notify über Libnotify (es ruft einer an) bekommt und ein (ich rufe an - Musik aus).
Was ist der Sinn der `notify`-Objekte? Das könnte eine Funktion sein, aber doch keine Klasse.
Da hast Du Recht, aber wie starte ich eine Funktion als Thread?
Alles, was ich im Web gefunden habe, hat bei mir nicht wie gewünscht funktioniert.
Allerdings bräuchte ich dann nicht eine Funktion sondern entweder mindestens 3 oder 6, jeh nachdem, wie ich die Funktion als Thread starte...
Die `Queue` würde ich übrigens nicht `pool` nennen, das ist von der Semantik her eine Jobqueue und kein Pool von Ressourcen, was man bei dem Namen `pool` eher erwarten würde.
Wird umbenannt.
Die `parse.run()` könnte man etwas mehr OOP gestalten. Zum Beispiel in dem man dynamisch `handle`-Methoden auf `parse`-Exemplaren aufruft, je nach Inhalt von ``info[2]``, was man auch an einen sprechenden Namen binden könnte, und die Werte im `connections`-Dictionary könnte man auch als Objekte modellieren.
Noch mehr Klasen bzw. Objekte?
Mal schauen, vielleicht kann ich ja etwas zusammenlegen.
In Zeile 52 gibt's übrigens ein Problem mit `indo` was wohl `info` heissen sollte.
Habe ich garnicht bemerkt, danke.

Viele Grüße
Maxi

P.S. Der Code ist noch nicht angepasst, mache ich jetzt aber.
maxi_king_333
User
Beiträge: 110
Registriert: Freitag 25. Dezember 2009, 03:42

Hi,

nun habe ich das Problem, dass die genrandomid() Funktion nicht global ist, ich kann sie also in den Klassen nicht verwenden.

So, nun ist es endlich auf BerliOS: http://developer.berlios.de/projects/fbcallnotify/
Unter GIT könnt Ihr euch den Code angucken bzw. herunterladen.
Habe auch die Änderungen da drin (funktioniert nur nicht, wegen genrandomid()).

Viele Grüße
Maxi

P.S. Ich hbae mal ein neues Thema unter Projekte erstellt, weil das passt nicht mehr so ganz zum ursprünglichen Thema: http://www.python-forum.de/topic-21399.html
Hier geht's dann weiter ;).
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Wobei ich mir nicht sicher bin, ob immer garantiert ist, dass man bei dem `recv()`-Aufruf Datenblöcke ganze Zeilen bekommt, und nicht auch mal eine Zeile über zwei `recv()`-Aufrufe verteilt sein kann!? Das sollte man klären.
mit recv() bekommt man nicht immer komplette Zeilen! es kann einem passieren das erst mit dem nächsten Zeilenblock die Zeile beendet wird, zum Beispiel durch \r\n

Edit: ich würde die If-Statements in der Funktion run in der parse.py durch ein dict ersetzten, z.B. so:

Code: Alles auswählen

class Parse(threading.Thread):
    def __init__(self, pool):
         threading.Thread.__init__(self)
         ....
         self.foo = {'bar' : self.on_bar}
    def run(self):
        ....
        if not info is None:
            if info[1] in self.foo:
                self.foo[info[1]](info)
the more they change the more they stay the same
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

maxi_king_333 hat geschrieben:Ich erzeuge 2, da ich irgendwie mit nur einer keine 10 Stelligen Zahlen hinbekomme.

Code: Alles auswählen

>>> '%010i' % randint(1, 9999999999)
'0084238386'
>>> 
MfG
HWK
BlackJack

PEP8 erlaubt zwar auch Tabs, bevorzugt aber ziemlich deutlich Leerzeichen: `For new projects, spaces-only are strongly recommended over tabs.` Wirklich ein Problem ist das vermischen von Tabs und Leerzeichen, da die meisten Leute aber Leerzeichen verwenden, wird es schwieriger Quelltext auszutauschen, wenn man Tabs verwendet.

Leerzeichen bekommt man mit dem richtigen Editor, also im Grunde jeder der als Editor zum Programmieren taugt, auch einfach wieder weg. Wenn ich die Rückschritt-Taste drücke, dann verschwinden bei eingerücktem Quellext auch gleich alle Leerzeichen die zu einer Ebene gehören und nicht nur ein Einzelnes. Eben das was man an der Stelle gerne hätte.

Mal davon abgesehen, dass es in der Standardbibliothek, insbesondere bei Python 2.x Namensgebungen gibt, die sich nicht an PEP8 halten, sind `os` und `sys` keine Klassen, sondern Module. Und als solche halten sie sich an die Empfehlungen von PEP8. `Tkinter` hält sich da zum Beispiel nicht dran, ist in Python 3 deshalb auch in `tkinter` umbenannt worden.

Klassen sind in sofern etwas besonderes als das sie a) eine Vorlage für Objekte von ihrem Typ sind und man b) davon andere Klassen ableiten kann. Ausserdem ist es praktisch, dass man, wenn einem kein besserer Name für ein Exemplar einfällt, einfach den Klassennamen klein geschrieben dafür verwenden kann. Also zum Beispiel bei einer Klasse `Person` kann man einfach ``person = Person('Klaus')`` schreiben. Die Standardbibliothek hält sich da auch nicht immer dran, und besonders bei `socket` habe ich schon geflucht. Wenn ich ein `socket.socket`-Exemplar erstelle, wäre `socket` oft ein passender Name dafür, aber den kann man ja leider nicht verwenden ohne Modul oder Klasse zu verdecken. Ich importiere den Typ deshalb immer so ``from socket import socket as Socket``.

Ich finde Operatoren ohne Leerzeichen seltsam. Liest sich zumindest IMHO schlechter wenn alles "zusammenklebt". Und das obwohl ich das früher auf dem C64 und auch in der Anfangszeit auf dem PC in BASIC und Pascal auch noch gemacht habe. Beim C64 hatte das aber auch einen Grund: nur 40 Zeichen pro (Bildschirm)Zeile und jedes gesparte Leerzeichen war ein gespartes Byte. :-)

Hm, tja *Zahlen* werden mit ``+`` halt addiert und nicht aneinandergehängt. Wieso Du eine 10-stellige Zahl nicht in einem Schritt hinbekommst, verstehe ich nicht:

Code: Alles auswählen

In [111]: n = random.randint(1000000000, 9999999999)

In [112]: n
Out[112]: 3779966062L

In [113]: len(str(n))
Out[113]: 10
Ich habe den Sinn der Dictionaries mit den Zufallszahlen als Schlüsseln auch nach der Beschreibung nicht verstanden. Vielleicht solltest Du solch eine Komplexität erst einbauen, wenn sie auch wirklich *gebraucht* wird, und nicht schon auf "Vorrat".

Funktionen kann man in einem Thread über die Klasse `threading.Thread` ausführen. Der kann man im Konstruktor ein aufrufbares Objekt und auch Argumente für diese Aufruf mitgeben.

Das eine Funktion nicht global ist, sollte in der Regel kein Problem sein, denn globale Funktionen sollte man ja nach Möglichkeit vermeiden. :-) Wenn man eine Funktion in mehreren Modulen braucht, schreibt man die in ein Modul, das die anderen Module dann importieren können. Wobei die Funktion ja letztendlich durch einen einzigen Aufruf von `random.randint()` ersetzt werden kann, also sich die Frage stellt, ob man dafür eine eigene Funktion braucht.
maxi_king_333
User
Beiträge: 110
Registriert: Freitag 25. Dezember 2009, 03:42

Hi,
Mal davon abgesehen, dass es in der Standardbibliothek, insbesondere bei Python 2.x Namensgebungen gibt, die sich nicht an PEP8 halten, sind `os` und `sys` keine Klassen, sondern Module. Und als solche halten sie sich an die Empfehlungen von PEP8. `Tkinter` hält sich da zum Beispiel nicht dran, ist in Python 3 deshalb auch in `tkinter` umbenannt worden.

Klassen sind in sofern etwas besonderes als das sie a) eine Vorlage für Objekte von ihrem Typ sind und man b) davon andere Klassen ableiten kann. Ausserdem ist es praktisch, dass man, wenn einem kein besserer Name für ein Exemplar einfällt, einfach den Klassennamen klein geschrieben dafür verwenden kann. Also zum Beispiel bei einer Klasse `Person` kann man einfach ``person = Person('Klaus')`` schreiben. Die Standardbibliothek hält sich da auch nicht immer dran, und besonders bei `socket` habe ich schon geflucht. Wenn ich ein `socket.socket`-Exemplar erstelle, wäre `socket` oft ein passender Name dafür, aber den kann man ja leider nicht verwenden ohne Modul oder Klasse zu verdecken. Ich importiere den Typ deshalb immer so ``from socket import socket as Socket``.
Em also das ist unlogisch oder verstehe ich das falsch?
Du sorgst dafür, dass socket in Socket umbenannt wird - weil die Namen ja groß sein sollen.
Und in Python 3 ist Tkinter in tkinter umbenannt worden - warum, ich dachte die Namen sollen groß sein.
Ansonsten - überredet - ich habe die Tabs durch Leerzeichen ersetzt.
Wieso Du eine 10-stellige Zahl nicht in einem Schritt hinbekommst, verstehe ich nicht:
Keine Sorge, ich auch nicht ;).
Auf wundersame Weise läuft jetzt das, was gestern so nicht gelaufen ist - vielleicht hatte ich irgendetwas übersehen oder falsch gemacht.
Naja, egal - es läuft.
Ich habe den Sinn der Dictionaries mit den Zufallszahlen als Schlüsseln auch nach der Beschreibung nicht verstanden. Vielleicht solltest Du solch eine Komplexität erst einbauen, wenn sie auch wirklich *gebraucht* wird, und nicht schon auf "Vorrat".
Es wird ja schon jetzt gebraucht, es fehlt einfach nur noch die Funktion, die die Konfiguration einliest - mehr Code, mehr Bugs, deshalb möchte ich, dass es erstmal so funktioniert.
Also, das soll ja ein Anrufmonitor werden.
Jetzt führst Du aber 2 Gespräche, dann brauchst Du auch 6 Objekte.
3 pro Gespräch Anruf/Angerufen Angenommen Aufgelegt.
Und da Anruf auch noch ausgeführt werden kann wenn man schon auflegt, muss es eben immer ein neues Objekt sein.
Diese brauchen auch irgendeinen Speicherort und dieser ist eben das Dict mit den Zufallszahlen.
Funktionen kann man in einem Thread über die Klasse `threading.Thread` ausführen. Der kann man im Konstruktor ein aufrufbares Objekt und auch Argumente für diese Aufruf mitgeben.
Danke, das wird doch dann durch target (Einfach der Name der Funktion) angegeben ,oder?

Code: Alles auswählen

threading.Thread(None, target)
Das eine Funktion nicht global ist, sollte in der Regel kein Problem sein, denn globale Funktionen sollte man ja nach Möglichkeit vermeiden. Smile Wenn man eine Funktion in mehreren Modulen braucht, schreibt man die in ein Modul, das die anderen Module dann importieren können. Wobei die Funktion ja letztendlich durch einen einzigen Aufruf von `random.randint()` ersetzt werden kann, also sich die Frage stellt, ob man dafür eine eigene Funktion braucht.
Und was ist, wenn es sich um eine Klasse handelt?
Naja, egal, ich habe jetzt einfach die Funktion direkt eingebaut.
mit recv() bekommt man nicht immer komplette Zeilen! es kann einem passieren das erst mit dem nächsten Zeilenblock die Zeile beendet wird, zum Beispiel durch \r\n
Aber die kommen vom Router und sind immer nur \n.
recv() liest doch einfach nur das aus, was der Socket empfangen hat, oder verstehe ich das falsch?
Und dann liest sie eben "test\ntest1\n" - wo liegt da das Problem?
Edit: ich würde die If-Statements in der Funktion run in der parse.py durch ein dict ersetzten, z.B. so:
Was für Vorteile soll das haben?
Das run() nicht so groß ist und schneller ausgeführt werden kann?
Dav1d hat geschrieben:Gut du verwendest dicts

Ich würde jetzt randomid durch eine Instanz einer Klasse austauschen, ich kenne deinen Code jetzt nicht
So ganz bin ich mit meiner bisherigen Struktur auch nicht zufrieden, da ich haufenweise Variablen habe, die die Verschiedenen Notify Stufen halten.
Diese Variablen müssen auch irgendwann gelöscht werden.
Am besten durch das Objekt dem sie zugeordnet sind.
Z.B. das "Objekt" als Schlüssel für das dict
So, das wollte ich eigentlich wissen, wie ich das machen soll.
Also es sollen ja nur nach Abschluss von dem Notifyer Thread die Objekte aus dem Zufallszahlen Dict gelöscht werden.

Viele Grüße
Maxi
Antworten