Black Friday = Pricewatch Bekijk onze selectie van de beste Black Friday-deals en voorkom een miskoop.

[Python] Exception handling met asyncore

Pagina: 1
Acties:

  • zeroxcool
  • Registratie: Januari 2001
  • Laatst online: 03-11 23:24
Ben een tijdje geleden mezelf wat in te lezen in Python. Nu ben ik bezig om een voorbeeld server en client te schrijven. Dat gaat geweldig met asyncore en asyn_chat. Echter, als het allemaal mooi meewerkt :). Ik heb het probleem even terug gebracht naar een simpele HTTP client. Stel ik wil connecten met een onbestaande host. Na een timeout zou je dus problemen moeten krijgen, die krijg ik ook. Dit wordt echter afgevangen door asyncore zelf (warning; unhandled exception).

Als ik de code dan even bekijk dan wordt dus een asyncore.handle_expt() functie gedraaid. Als ik die overload dan weet ik dat er 'iets' fout is gegaan. Maar waarom kan ik niet 'gewoon' een exceptie afvangen bij het punt waar het dreigt mis te gaan. Zoals ik hieronder probeer:
Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import asyncore, socket

class http_client(asyncore.dispatcher):

    def __init__(self, host, path):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)

        try:
            self.connect( (host, 80) )
        except socket.error:
            print "socket error"
        except socket.timeout:
            print "socket timeout"
        except:
            print "standard exception"
        else:
            self.buffer = 'GET %s HTTP/1.0\r\n\r\n' % path

    def handle_connect(self):
        print "connected"

    def handle_close(self):
        self.close()

    def handle_read(self):
        print self.recv(8192)

    def writable(self):
        return (len(self.buffer) > 0)

    def handle_write(self):
        sent = self.send(self.buffer)
        self.buffer = self.buffer[sent:]

c = http_client('www.nietbestaandiets.org', '/')
asyncore.loop()


Je ziet dat de exceptions die ik af probeer te vangen nooit getriggered worden. Wat is hier aan te doen?

zeroxcool.net - curity.eu


  • wjv
  • Registratie: December 2003
  • Laatst online: 17-11 14:20

wjv

Wanneer ik de code uitvoer met kleine aanpassing; buffer in init toegevoegd en exception string bij socket.error :
Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import asyncore, socket

class http_client(asyncore.dispatcher):

    def __init__(self, host, path):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.buffer = ''

        try:
            self.connect( (host, 80) )
            print "after connect"
        except socket.error, e:
            print "socket error", str(e)
        except socket.timeout:
            print "socket timeout"
        except:
            print "standard exception"
        else:
            self.buffer = 'GET %s HTTP/1.0\r\n\r\n' % path

    def handle_connect(self):
        print "connected"

    def handle_close(self):
        self.close()

    def handle_read(self):
        print self.recv(8192)

    def writable(self):
        return (len(self.buffer) > 0)

    def handle_write(self):
        sent = self.send(self.buffer)
        self.buffer = self.buffer[sent:]

c = http_client('www.nietbestaandiets.org', '/')
asyncore.loop()


Krijg ik dit als uitvoer :

code:
1
2
3
aitken>python test.py
socket error (-2, 'Name or service not known')
connected


De socket.error wordt bij mij dus wel afgevangen. Dit is op Linux.

  • zeroxcool
  • Registratie: Januari 2001
  • Laatst online: 03-11 23:24
Mmm, heb het foute voorbeeld gegeven :). Probeer eens een niet werkend IP-adres: 10.0.0.123 of zoiets. Onder Linux krijg ik dan zoiets:
harm@vps:~/python$ python test.py
after connect
connected
error: uncaptured python exception, closing channel <__main__.http_client connected at -0x482c7314> (socket.error:(113, 'No route to host') [asyncore.py|read|69] [asyncore.py|handle_read_event|389] [test.py|handle_read|29] [asyncore.py|recv|343])


En onder Windows een oneindig aantal 'warning: unhandled exception', na zo'n dikke 25 seconden wachten.

zeroxcool.net - curity.eu


Verwijderd

Asyncore staat erom bekend dat het bagger met de errors van Python om gaat. Het is misschien beter om de "defacto standaard" te gebruiken. Namelijk Twisted.

Wat er waarschijnlijk gebeurt is dat asyncore de error afvangt maar hem helaas niet opnieuw raised waardoor jij er niets meer mee kan.

Wat gebeurd er als je asyncore.handle_expt() overload met iets dat alleen dit doet? Heb zelf nog niet met asyncore geklooid :)
code:
1
2
3
class asyncore_error(asyncore):
    handle_expt()
        raise
zeroxcool schreef op donderdag 31 juli 2008 @ 18:59:
Mmm, heb het foute voorbeeld gegeven :). Probeer eens een niet werkend IP-adres: 10.0.0.123 of zoiets. Onder Linux krijg ik dan zoiets:
harm@vps:~/python$ python test.py
after connect
connected
error: uncaptured python exception, closing channel <__main__.http_client connected at -0x482c7314> (socket.error:(113, 'No route to host') [asyncore.py|read|69] [asyncore.py|handle_read_event|389] [test.py|handle_read|29] [asyncore.py|recv|343])


En onder Windows een oneindig aantal 'warning: unhandled exception', na zo'n dikke 25 seconden wachten.
Dat laatste zal ermee te maken hebben dat asyncore niet breekt op een error en vervolgens een while loop data probeert te laten uitlezen van een socket dat niet bestaat.

[ Voor 43% gewijzigd door Verwijderd op 31-07-2008 20:38 ]


  • user109731
  • Registratie: Maart 2004
  • Niet online
Is handle_error niet wat je zoekt:
Python:
1
2
3
4
5
class http_client(asyncore.dispatcher):
  
  def handle_error(self):
    print "Error!"
    raise

handle_expt is voor out-of-band data.

  • zeroxcool
  • Registratie: Januari 2001
  • Laatst online: 03-11 23:24
JanDM schreef op donderdag 31 juli 2008 @ 21:06:
Is handle_error niet wat je zoekt:
Python:
1
2
3
4
5
class http_client(asyncore.dispatcher):
  
  def handle_error(self):
    print "Error!"
    raise

handle_expt is voor out-of-band data.
Op m'n Linux machine (versie zie output) doet dit de trick:
harm@vps:~/python$ python test.py
2.4.4 (#2, Apr 15 2008, 23:43:20)
[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)]
after connect
connected
error occured
Traceback (most recent call last):
  File "test.py", line 45, in ?
    asyncore.loop()
  File "/usr/lib/python2.4/asyncore.py", line 192, in loop
    poll_fun(timeout, map)
  File "/usr/lib/python2.4/asyncore.py", line 133, in poll
    read(obj)
  File "/usr/lib/python2.4/asyncore.py", line 73, in read
    obj.handle_error()
  File "/usr/lib/python2.4/asyncore.py", line 69, in read
    obj.handle_read_event()
  File "/usr/lib/python2.4/asyncore.py", line 389, in handle_read_event
    self.handle_read()
  File "test.py", line 30, in handle_read
    print self.recv(8192)
  File "/usr/lib/python2.4/asyncore.py", line 343, in recv
    data = self.socket.recv(buffer_size)
socket.error: (113, 'No route to host')

Echter, op m'n Windows machine blijft hij continue die warning genereren. Dat is een andere versie (2.5.2 (r252:60911, Feb 21 2008, 13:11:45) [MSC v.1310 32 bit (Intel)]). Deze bugreport meldt een beetje het probleem wat ik heb, maar een oplossing/fix is niet gemeld...

Wel gek trouwens dat handle_connect() sowieso wordt aangeroepen. Terwijl dat juist gefaald heeft...

zeroxcool.net - curity.eu

Pagina: 1