[Twisted-Python] Re: A Python metaclass for Twisted allowing __init__ to return a Deferred

Terry Jones terry at jon.es
Sat Dec 6 01:06:36 MST 2008


Hi Nicola!

>>>>> "Nicola" == Nicola Larosa <nico at teknico.net> writes:
Nicola> Terry Jones wrote:
>> BTW, I spent an interesting morning getting my head around *exactly* how
>> inlineCallbacks does its thing... No summary of my thoughts could do it
>> justice. I wonder how many people on the planet have been down that
>> rabbit hole.

Nicola> Not me, man, not me. I just use the bloody thing, and curse it when
Nicola> it shortens tracebacks.

I know exactly what you're talking about, and I hated that too. But I dug
into that and found out where the problem was: I didn't know Python well
enough :-)

I bet you're doing something like this:

@inlineCallbacks
def f():
    # Whatever
    try:
        # Your code here
    except Exception, e:
        # Do some cleaning up, maybe write to the log, maybe call another
        # function that uses inlineCallbacks
        raise e

or just

@inlineCallbacks
def f():
    # Whatever
    try:
        # Your code here
    except Exception:
        # Do some cleaning up, maybe write to the log, maybe call another
        # function that uses inlineCallbacks
        raise


The problem here is that you're not using the 3-argument form of raise. So
you're either dropping information (with the raise e) or pulling out the
last exception (with the no-arg raise).

Consider the latter case. Suppose your cleanup code calls another function
that uses inlineCallbacks. That function will eventually raise
StopIteration or raise via calling defer.returnValue. So by the time
control returns to your code, your raise (which implicitly uses
sys.exc_info()) raises the wrong exception! So you get e.g., a
StopIteration exception coming at you out of your inlineCallbacks function
and you curse the thing :-) This applies if your cleanup code calls any
iterator, or if you call something that try/except catches a KeyError, etc.

So just use

@inlineCallbacks
def f():
    # Whatever
    try:
        # Your code here
    except Exception:
        info = sys.exc_info()
        # Do some cleaning up, maybe write to the log, maybe call another
        # function that uses inlineCallbacks
        raise info[0], info[1], info[2]

and it just works. Try it :-) You cant do anything nice like raise *info
because Python's parser doesn't like that (AFAIR).

I nearly posted about this to the list, but I figured it might help if I
had more of a clue about Python itself, seeing as what I was doing was
nothing to do with Twisted.


>> I hope people don't mind my peanut gallery commentary. We're all in this
>> together, after all. A little gallows humor occasionally seems in order.
Nicola> Again, certainly not me. Go right ahead! ;-)

Don't encourage me...

Terry




More information about the Twisted-Python mailing list