SocketServer und epoll

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
der_Angler
User
Beiträge: 25
Registriert: Montag 28. Januar 2013, 00:48

es wird heiß, ich kann es spüren ...

Code: Alles auswählen

pi@raspberrypi ~ $ python RaPiServer2.py
Traceback (most recent call last):
  File "RaPiServer2.py", line 129, in <module>
    pollster.register(Switch(light_bed_switch, light_bed), select.EPOLLIN | select.EPOLLET)
TypeError: argument must be an int, or have a fileno() method.
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

der_Angler hat geschrieben:es wird heiß, ich kann es spüren ...
naja, freu Dich nicht zu früh.

das sind nur so Kleinigkeiten, die beim Remote-Debuggen nach und nach auftauchen.
»fileno« fehlt:

Code: Alles auswählen

class Switch(object):
    def __init__(self, switch, light):
        self.switch = switch
        self.light = light
        self.fileno = switch.fileno
        asyncore.socket_map[switch.fileno()] = self
der_Angler
User
Beiträge: 25
Registriert: Montag 28. Januar 2013, 00:48

@Sirius3
Sagmal, du hättest kein Interesse an einem RaspberryPi?

Weil du hilfst mir hier dermaßen, ich frag mich die ganze Zeit wie ich mich bedanken kann.
Und da ich hier zuhause 3-4 Raspberrys rumliegen habe würde ich dir einfach einen schenken, quasi als Dankeschön und zum Testen :)
der_Angler
User
Beiträge: 25
Registriert: Montag 28. Januar 2013, 00:48

naja, freu Dich nicht zu früh.
Hmm, da hattest du wohl recht, ein neuer Fehler

Code: Alles auswählen

pi@raspberrypi ~ $ python RaPiServer2.py
Traceback (most recent call last):
  File "RaPiServer2.py", line 134, in <module>
    readwrite(fd, flags)
  File "RaPiServer2.py", line 117, in readwrite
    obj.handle_error()
AttributeError: 'int' object has no attribute 'handle_error'
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

der_Angler hat geschrieben:PS: Python Einsteiger Buch ist bereits bestellt.
Welches? Hoffentlich keines von Galileo.
In specifications, Murphy's Law supersedes Ohm's.
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Ich hoffe, Du verstehst noch einigermaßen, wie das Programm aufgebaut ist,
falls nicht, fragen! und nicht nur Fehlermelden¡

epoll nimmt zwar file-like-Objekte entgegen, gibt aber nur Filehandles zurück :(
Deshalb noch ein kleiner epoll-Wrapper

Code: Alles auswählen

class EPoll(object):
    def __init__(self):
        self.epoll = select.epoll()
        self.fdmap = {}
        
    def register(self, obj, flags):
        fd = obj.fileno()
        self.epoll.register(fd, flags)
        self.fdmap[fd] = obj

    def unregister(self, obj):
        fd = obj.fileno()
        del self.fdmap[fd]
        self.epoll.unregister(fd)
        
    def poll(self):
        evt = self.epoll.poll()
        for fd, flags in evt:
            yield self.fdmap[fd], flags

if __name__ == "__main__":
    with exported(GPIOPin(pin_bed, direction=Out)) as light_bed, \
        exported(GPIOPin(pin_bed_switch, Pin.In, Pin.Rising)) as light_bed_switch, \
        exported(GPIOPin(pin_nightlight, direction=Out)) as light_nightlight:

        light_bed.value = 0
        light_nightlight.value = 0

        pollster = EPoll()
        pollster.register(Server(("",54321),pollster), select.EPOLLIN)
        pollster.register(Switch(light_bed_switch, light_bed), select.EPOLLIN | select.EPOLLET)
        while True:
            evt = pollster.poll()
            for obj, flags in evt:
                readwrite(obj, flags)
der_Angler
User
Beiträge: 25
Registriert: Montag 28. Januar 2013, 00:48

naja, ich blicke so halbwegs durch.

Ich versuche halt immer auf die schnelle deine Änderungen und poste das Ergebnis damit du entsprechendes Feedback hast.

Wenn alles richtig läuft setze ich mich hin und gehe jede Zeile einzel durch.
Die prinzipielle Funktionsweise verstehe ich aber schon.

Okay, habe das Programm entsprechend geändert.

Nach dem Starten erscheint:

Code: Alles auswählen

pi@raspberrypi ~ $ python RaPiServer2.py
something went wrong
was aber nicht schlimm ist weil der Hardware-Button funktioniert.

Drücke ich den Taster geht die LED an, bzw. wieder aus.
Trotzdem erscheint jedes mal wenn ich den Taster drücke die Fehlermeldung "something went wrong" - das sieht dann so aus

Code: Alles auswählen

pi@raspberrypi ~ $ python RaPiServer2.py
something went wrong
something went wrong
something went wrong
something went wrong
Beflügelt vom Erfolg wollte ich dann auch mal die Netzwerkfunktionen testen und hab die Handy-App gestartet.
Leider kam direkt beim starten der App (und damit beim verbinden mit dem Skript) ein Fehler und das Skript hat auch nicht auf die Netzwerkbefehle reagiert.

Code: Alles auswählen

pi@raspberrypi ~ $ python RaPiServer2.py
something went wrong
something went wrong
something went wrong
something went wrong
Connected from ('192.168.2.113', 43029)
error: uncaptured python exception, closing channel <__main__.Server listening :54321 at 0x4056b4e0> (<type 'exceptions.AttributeError'>:'module' object has no attribute 'EPOLLNVAL' [RaPiServer2.py|readwrite|107])
error: uncaptured python exception, closing channel <__main__.Client connected 192.168.2.113:43029 at 0x4056b7d8> (<type 'exceptions.AttributeError'>:'module' object has no attribute 'EPOLLNVAL' [RaPiServer2.py|readwrite|107])
Ds verstehen fällt mir zum teil noch schwer, für ein Anfänger ist das Thema aber auch durchaus komplex.
Mein Glück das ich nen paar andere Programmiersprachen kenne und sich alle ähnlich sind.

Seltsamerweise fand ich die erste Version des Skripts von dir (die ohne epoll) einfacher zu verstehen.
Mit epoll habe ich irgendwie Schwierigkeiten.
BlackJack

`select.EPOLLNVAL` gibt es nicht.
der_Angler
User
Beiträge: 25
Registriert: Montag 28. Januar 2013, 00:48

okay wenn ich in der entsprechenden Zeile folgendes

Code: Alles auswählen

        if flags & (select.EPOLLHUP | select.EPOLLERR | select.EPOLLNVAL):
durch

Code: Alles auswählen

        if flags & (select.EPOLLHUP | select.EPOLLERR | select.POLLNVAL):
austausche dann scheint tatsächlich alles zu funktionieren.
Ich bekomme zwar immernoch die Meldung

Code: Alles auswählen

pi@raspberrypi ~ $ python RaPiServer2.py
something went wrong
something went wrong
something went wrong
something went wrong
Connected from ('192.168.2.113', 48439)
something went wrong
something went wrong
something went wrong
something went wrong
wenn ich die Hardware Taste drücke, aber es funktioniert :)

Sollte also anstatt "EPOLLNVAL" -> "POLLNVAL" der ganze Fehler gewesen sein?
Und ist es okay das einfach so abzuändern?

Und schon mal vielen Dank an alle und an Sirius im Besonderen :)
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Das something went wrong ist die sehr einfache Fehlerbehandlung.
Du solltest hier:

Code: Alles auswählen

def readwrite(obj, flags):
    try:
        if flags & select.EPOLLIN:
            obj.handle_read_event()
        if flags & select.EPOLLOUT:
            obj.handle_write_event()
        if flags & select.EPOLLPRI:
            obj.handle_expt_event()
        if flags & (select.EPOLLHUP | select.EPOLLERR | select.EPOLLNVAL):
            obj.handle_close()
    except socket.error, e:
        if e.args[0] not in asyncore._DISCONNECTED:
            obj.handle_error()
        else:
            obj.handle_close()
    except asyncore._reraised_exceptions:
        raise
    except:
        obj.handle_error()
vor allen die letzten beiden Zeilen noch erweitern, damit Du auch
weißt was für eine Exception, samt Traceback aufgetreten ist.
Es werden nämlich alle Fehler (auch falsch geschriebene Variablennamen)
einfach geschluckt.
Aber das überlass ich dir als Hausaufgabe.
der_Angler
User
Beiträge: 25
Registriert: Montag 28. Januar 2013, 00:48

Hmm, dann will ich mich am Wochenende mal hinsetzen und werde über den Hausaufgaben brüten.

Ich hoffe ich kann dann am Montag eine gute Lösung posten :)
der_Angler
User
Beiträge: 25
Registriert: Montag 28. Januar 2013, 00:48

So,
ich habe mal versucht mich in das Thema "Error-Handling" einzulesen, muss aber sagen das es im Augenblick noch meinen Horizont übersteigt.
Ich konnte also meine Hausaufgabe nicht machen, da das Script aber trotzdem tut was es soll scheint der Fehler auch nicht weiter schlimm zu sein.

ich nutze mittlerweile 2 x Versionen. Eine auf dem RaspberryPi mit Hardware-Buttons (und Fehlermeldung) und eine auf dem Media-Server ohne Buttons (und ohne Fehler).
Dank dir bin ich jetzt soweit das ich eine USB-Steckdosenleiste, diverse Funkempfänger von HomeEasy und xbmc bequem übers Handy steuern kann.

Dafür wollte ich mich noch einmal herzlich bedanken :)
der_Angler
User
Beiträge: 25
Registriert: Montag 28. Januar 2013, 00:48

Hallo,

nach langer Zeit muss ich mich mal wieder melden.

Erst einmal danke an das Script, das funktioniert soweit unter Linux sehr gut :)

Dafür tausend Dank!!!

Aber, unter Windows mit python 3.2 sieht die Welt leider ganz anders aus, versuche ich das Script unter Windows laufen zu lassen, dann bekomme ich jede Menge bezüglich ".epoll()" - es scheint als kenne python unter windows diesen Befehl nicht.
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

@der_Angler: falls Du die Dokumentation gelesen hast, wüstest Du, dass es epoll nur unter Linux gibt.
der_Angler
User
Beiträge: 25
Registriert: Montag 28. Januar 2013, 00:48

okay, dann habe ich das schon einmal richtig verstanden ... hatte sowas gelesen aber gedacht ich hätte es falsch verstanden.

Hmm, okay, dann muss ich in dem Fall also ein Script für Linux und eins für Windows nutzen?

Schade, da ich unter Windows mit Eclipse entwickle, da bekomme ich dann auch in zukunft weiter Fehler angezeigt.
Trotzdem erst mal danke.
Antworten