[Stackless] Re: Stackless API

Kristján V. Jónsson kristjan at ccpgames.com
Tue Feb 3 11:27:34 CET 2004

It´s well and good to be able to raise exceptions on the other side of a channel with "send_exception()".  But what if you want to reraise an exception that you catch?  For example:  The tasklet is servicing some request, and wants to give results back to someone listening on a channel.

def my_task():
        result = self.do_my_stuff()
    except Exception, e:

Now, the original traceback of the exception is lost, right?
Hm, because of the daft way python exceptions work,  PyErr_Orccurred() is probably true in the send_exception() execution, with the traceback still hanging in there and so it could be salvaged.  Otherwise, some sort of channel.reraise_exception()?

(I always found it stupid how the exception and related data just exists globally in the thread state and lingers on.  When you reraise, you raise the current exception with the current traceback...  And as we know, in stackless this can cause a lot of tracebacks to linger on since there is no simple way to clear them from python... but that´s another story.


-----Original Message-----
From: stackless-bounces at stackless.com [mailto:stackless-bounces at stackless.com] On Behalf Of Esteban U. Caamano Castro
Sent: 3. febrúar 2004 09:50
To: Christian Tismer
Cc: stackless at stackless.com
Subject: Re: [Stackless] Re: Stackless API

> I gues that raising a bomb on a channels is not the
> most
> common action unless you are the roadrunner coyote,


> so maybe it would be most efficient to use a special
> object as a marker flag? This object could be solely
> visible
> to channels.

Yes, this is Tirosh' proposal.

Assume that you have a channel class with no exception
support whatsoever. You could implement
exception sending on top of that, like this

class CoyoteChannel(stackless.channel):

    class __ExceptionWrapper:
        def __init__(self, exc):
            self.exc = exc

    def send_exception(self, exc):

    def receive(self):
        o = stackless.channel.receive(self)
        if getattr(o, '__class__', None) is \
            raise o.exc
            return o

> Other proposals?

If you really want to minimize the performance impact
to users that never call send_exception(), you can do
it (down to exactly zero), by just using the default
receive() (which doesn't check for exceptions) until
the first time send_exception is called. You then
overwrite receive() for this channel instance:

class Channel(stackless.channel):
    def __init__(self):
        self.send_exception = \

    class __ExceptionWrapper:
        def __init__(self, exc):
            self.exc = exc

    def __first_send_exception(self, exc):
        self.receive = self.__receive
        self.send_exception = self.__send_exception

    def __send_exception(self, exc):

    def __receive(self):
        o = stackless.channel.receive(self)
        if getattr(ret, '__class__', None) \
                        is self.__ExceptionWrapper:
            raise o.exc
            return o

For those who use exceptions to implement iterators,
this approach involves practically no overhead over an
exceptionless channel. For those that want to continue
sending data after the first exception is received
(e.g. if you use channels to implement RPCs), the
check for __ExceptionWrapper is well warranted.

The drawback of this hacky approach is that people who
want to further subclass channel will maybe live
interesting times :).

Finally, the fact that you can do this so easily in
python on top of a totally exceptionless channel
demonstrates that it's not essential, implementation
wise, to have it in the core. Maybe some
stacklessutil.CoyoteChannel would pretty much do the
trick for all interested?



Yahoo! GeoCities: 15MB de espaço grátis para criar seu web site!

Stackless mailing list
Stackless at stackless.com

Stackless mailing list
Stackless at stackless.com

More information about the Stackless mailing list