Parallele Prozesse

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
glaslos
User
Beiträge: 23
Registriert: Donnerstag 12. Februar 2009, 18:55
Kontaktdaten:

Hallo,
ich schreibe gerade an einem IRC Log Bot. Gedacht ist, dass der Bot in meinem Hauptprogramm in einem Thread läuft und die Einträge in einem Logfile in einen IRC Channel schreibt.

Der IRC Bot ist kein Problem, das Handshake klappt ebenfalls prima. Folgendermaßen arbeitet der Bot:

Code: Alles auswählen

while 1:
    readbuffer=readbuffer+s.recv(1024)
    temp=string.split(readbuffer, "\n")
    readbuffer=temp.pop()
    
    for line in temp:
        line=string.rstrip(line)
        line=string.split(line)
        if line == pattern:
            handle line
Nun möchte ich parallel das Logfile öffnen und auf neue Einträge warten:

Code: Alles auswählen

while 1:
    f = open("logfile.txt")
    line = f.readline()
    if line != "":
        s.send(line)
Ich habe nun das Problem, dass die While Schleifen parallel laufen müssen. Habe ich beides in einer Schleife, wird das logfile erst abgerufen, wenn wieder Daten über den Socket fließen, was eindeutig nicht im Sinne des Erfinders ist.

Wie löse ich das nun am besten? Lege ich "um" das recv ein "Timeout" und arbeite die Schleife weiter ab?

Ich wäre dankbar für Hilfe und oder einen Denkanstoß.
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Stichwort Threads ;-)
glaslos
User
Beiträge: 23
Registriert: Donnerstag 12. Februar 2009, 18:55
Kontaktdaten:

Dauerbaustelle hat geschrieben:Stichwort Threads ;-)
Verstehe ich dich richtig, dass du vorschlägst, die beiden while Schleifen in extra Threads zu packen? Ich werde das mal versuchen. Ein Problem wird die Verständigung zwischen den Threads. Ich muss dem "LogThread" irgend wie mitteilen, wann der Bot im Channel ist, was ich im "IRCThread" erfahren werde, mache ich das über ein Event?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ganz normal über Nachrichten. Wenn du eine Klasse von `threading.Thread` erben lässt, kannst du auch gleich Methoden einbauen, die dir deine Funktionalität - die ich grad nicht so recht durchblicke, is wohl schon zu spät - implementieren.

Aber in dem Schnipsel seh ich ein paar Probleme:
1. Die Funktionen aus dem `string`-Modul, die du da verwendest sind deprecated (unter der Annahme, dass du keine antike Version verwendest). Du solltest die entsprechenden Methoden des Strings benutzen, den du der Funktion übergibst.
2. Wenn du Endlosschleifen baust, dann am besten mit `while True:` Python kann nämlich sprechen ;)
3. Schau dir mal [wiki]PEP 8 (Übersetzung)[/wiki] bzw das Orginal an.
glaslos
User
Beiträge: 23
Registriert: Donnerstag 12. Februar 2009, 18:55
Kontaktdaten:

Ich habe mal versucht, alle genannten Punkte umzusetzen. Mittlerweile funktionier es auch wie gewünscht :) Ich danke für die Hilfe und Anregungen!

Code: Alles auswählen

import threading
import socket

class ircbot():
    """IRC client class"""
    def __init__(self):
        self.ircserver=""
        self.ircport=
        self.nick=""
        self.ident=""
        self.realname=""
        self.channel=""
        self.s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.s.connect((self.ircserver, self.ircport))
        self.s.send("NICK %s\r\n" % self.nick)
        self.s.send("USER %s %s bla :%s\r\n" % (self.ident, self.ircserver, self.realname))

    def ircthread(self):
        """IRC client
        
        This function joins the irc channel and reads incoming
        data on the socket. 
        
        """
        self.joined = False
        readbuffer = ""
        while True:
            readbuffer=readbuffer+self.s.recv(1024)
            temp=readbuffer.split("\n")
            readbuffer=temp.pop()
            for line in temp:
                line=line.rstrip()
                line=line.split()
                print line
                if(line[0]=="PING"):
                    self.s.send("PONG %s\r\n" % line[1])
                if line[1] == '001':
                    self.s.send("JOIN %s\r\n" % self.channel)
                if line[1] == '366':
                    self.joined = True
    
    def logthread(self):
        """IRC logging function
        
        This function reads the log file and sends new entries
        to the irc channel.
        
        """
        f = open("res/logfile.txt")
        while True:
            if self.joined == True:
                line = f.readline()
                if line != "":
                    # Send the log file line to the channel
                    self.s.send("PRIVMSG %s :%s\r\n" % (self.channel, line))

if __name__ == '__main__':
    bot = ircbot()
    ircthread = threading.Thread(target=bot.ircthread)
    logthread = threading.Thread(target=bot.logthread)
    ircthread.start()
    logthread.start()
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Nuja, so war das eigentlich nicht gedacht. Aber wenn du damit zufrieden bist, solltest du die Klasse zumindest new-style machen, dh von `object` erben lassen.
Benutzeravatar
cryzed
User
Beiträge: 82
Registriert: Samstag 28. März 2009, 15:53

cofi hat geschrieben:Nuja, so war das eigentlich nicht gedacht. Aber wenn du damit zufrieden bist, solltest du die Klasse zumindest new-style machen, dh von `object` erben lassen.
Oder die python-irclib benutzen.
glaslos
User
Beiträge: 23
Registriert: Donnerstag 12. Februar 2009, 18:55
Kontaktdaten:

cofi hat geschrieben:Nuja, so war das eigentlich nicht gedacht. Aber wenn du damit zufrieden bist, solltest du die Klasse zumindest new-style machen, dh von `object` erben lassen.
Kannst du mir genauer erklären, in wie weit sich das von meinem Beispiel unterschiedet?
cryzed hat geschrieben:Oder die python-irclib benutzen.
Das ist ja nicht das Problem ;)
tordmor
User
Beiträge: 100
Registriert: Donnerstag 20. November 2008, 10:29
Wohnort: Stuttgart

Dauerbaustelle hat geschrieben:Stichwort Threads ;-)
Argh! Nein! Threads machen alles nur schlimmer. Das richtige Stichwort ist select.
http://www.felix-benner.com
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

glaslos hat geschrieben:Kannst du mir genauer erklären, in wie weit sich das von meinem Beispiel unterschiedet?
Es unterscheidet sich nur Zeile 5:

Code: Alles auswählen

class ircbot(object):
Für die Vorteile suchst du am besten nach "Unterschiede old-style new-style Klassen", daneben sind old-style Klassen deprecated ;)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

cofi hat geschrieben:daneben sind old-style Klassen deprecated ;)
Sind sie nicht. Sie sind einfach in Python 3.x nicht mehr da, aber es gibt AFAIR keine Deprecation für diese Klassen in 2.x. Natürlich sollte man sie aber trotzdem nicht mehr nutzen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten