Exception feature creep! (was: re-entering in the normal flow after an exception is raised)

Discussion in 'Python' started by Lonnie Princehouse, Oct 1, 2004.

  1. In a recent post, Michele Simionato asked about resumable (or
    re-entrant) exceptions, the basic idea being that when raised and
    uncaught, these exceptions would only propagate backwards through a
    limited number of frames before being implicitly ignored. Alex
    Martelli pointed out that resumable exceptions are difficult to
    implement, and that the need for them isn't pressing because it's
    pretty easy to write a program with explicit error handling that works
    just fine, citing Bjarne Stroustrup's thoughts on the same topic for
    C++.
    This is probably quite right.

    Nonetheless, I tried to write some demo code that implemented
    resumable exceptions, but ran face-first into a brick wall: I
    couldn't find any way to manipulate the call stack (to execute code in
    a frame other than the current one)

    What if exceptions were given more control?

    Proposal:

    1. Call a __raise__ method in the exception when raised
    2. Call an __uncaught__ method in every frame for which the exception
    is not handled by an except clause. __uncaught__ would decide
    whether or not to continue to propagate the exception to the next
    frame. If __uncaught__ decides to abort the exception, then the
    calling statement is aborted/ignored--- the implicit equivalent of:

    try:
    do_something()
    except:
    pass


    Anyway, this is just idle speculation. I don't really see a need for
    it, but it's interesting to ponder.


    Here are some hypothetical uses:


    1. An exception that propagates only n frames:

    class QuietException(Exception):
    def __init__(self, n):
    Exception.__init__(self)
    self.n = n

    def __raise__(self):
    self.counter = self.n

    def __uncaught__(self):
    if self.counter > 0:
    self.counter -= 1
    return True
    else:
    return False

    2. An exception that keeps a traceback as it goes:

    class TracingException(Exception):

    def __raise__(self):
    self.traceback = []

    def __uncaught__(self):
    self.traceback.append(sys._getframe(1))

    ....

    try:
    foo()
    except TracingException, e:
    # isn't this more elegant than sys.last_traceback?
    import traceback
    traceback.print_tb(e.traceback)


    3. An exception that resumes execution if some global FAULT_TOLERANT
    is true:

    class FaultTolerantException(Exception):
    def __uncaught__(self):
    return not FAULT_TOLERANT
    Lonnie Princehouse, Oct 1, 2004
    #1
    1. Advertising

  2. Re: Exception feature creep! (was: re-entering in the normal flowafter an exception is raised)

    Lonnie Princehouse ha scritto:

    > In a recent post, Michele Simionato asked about resumable (or
    > re-entrant) exceptions, the basic idea being that when raised and
    > uncaught, these exceptions would only propagate backwards through a
    > limited number of frames before being implicitly ignored.


    I don't understand: why resumable exceptions should be ignored after
    they propagate for a limited number of frames?

    the only idea of resumable exceptions I have is that they allow you to ,
    well, resume excution from the point they were raised.
    gabriele renzi, Oct 1, 2004
    #2
    1. Advertising

  3. Re: Exception feature creep! (was: re-entering in the normal flowafteran exception is raised)

    gabriele renzi wrote:

    > I don't understand: why resumable exceptions should be ignored after
    > they propagate for a limited number of frames?
    >
    > the only idea of resumable exceptions I have is that they allow you to
    > ,
    > well, resume excution from the point they were raised.


    Right. The idea is that you can catch the exception and resume it, in
    which case execution continues from the point that the resumable
    exception was _raised_. The exception, when caught, can still be
    reraised (and another catcher resuming it will still cause it to resume
    from the original point it was raised). If the exception is not caught,
    then it acts as a normal exception and halts the program with a stack
    trace.

    --
    __ Erik Max Francis && && http://www.alcyone.com/max/
    / \ San Jose, CA, USA && 37 20 N 121 53 W && AIM erikmaxfrancis
    \__/ The color is red / Under my shoe
    -- Neneh Cherry
    Erik Max Francis, Oct 1, 2004
    #3
  4. (Lonnie Princehouse) wrote in message news:<>...
    > In a recent post, Michele Simionato asked about resumable (or
    > re-entrant) exceptions, the basic idea being that when raised and
    > uncaught, these exceptions would only propagate backwards through a
    > limited number of frames before being implicitly ignored.


    Well, actually that is NOT what I asked. Erik Max Francis got my point:

    """
    The idea is that you can catch the exception and resume it, in
    which case execution continues from the point that the resumable
    exception was _raised_. The exception, when caught, can still be
    reraised (and another catcher resuming it will still cause it to resume
    from the original point it was raised). If the exception is not caught,
    then it acts as a normal exception and halts the program with a stack
    trace.
    """

    I have no idea about how difficult would be to implement resumable exceptions
    in Python; also I am not sure about their cost vs. benefit. For sure, in
    2.5 years of Python programming this is first time I have got an use case
    for resumable exceptions; still it is a contrived case. So, I am not in
    dire need of resumable exceptions.
    Nevertheless, it is possible that if we had resumable exceptions we
    could use them as a control flow structure in non-exceptional situations.
    One could speculate about the idea ...

    Michele Simionato
    Michele Simionato, Oct 2, 2004
    #4
  5. Re: Exception feature creep! (was: re-entering in the normal flow afteran exception is raised)

    Michele Simionato wrote:

    > I have no idea about how difficult would be to implement resumable
    > exceptions
    > in Python; also I am not sure about their cost vs. benefit. For sure,
    > in
    > 2.5 years of Python programming this is first time I have got an use
    > case
    > for resumable exceptions; still it is a contrived case. So, I am not
    > in
    > dire need of resumable exceptions.
    > Nevertheless, it is possible that if we had resumable exceptions we
    > could use them as a control flow structure in non-exceptional
    > situations.
    > One could speculate about the idea ...


    Resumable exceptions are for when you want to flag cases that may be
    exceptional, but that some users of the library may not care about. A
    good example would be a forgiving parser, where resumable exceptions
    would be thrown whenever a technical violation, but one that can be
    recovered from, occurs. This is actually a lot more common than you
    think; Web browsers and server-side email processing systems are good
    examples, where you may want to know about technical violations of
    standards and RFCs, but still need to do something meaningful anyway.
    In those cases, someone using the library can not bother catching those
    resumable exceptions, in which case they'll act as normal exceptions, or
    they can catch them and do something meaningful with them, or they can
    simply blanket catch them and immediately resume, something like:

    ...
    except (FirstResumableException, SecondResumableException), e:
    e.resume()

    Obviously, there are other ways to accomplish this, but they have to use
    some mechanism other than exceptions.

    --
    __ Erik Max Francis && && http://www.alcyone.com/max/
    / \ San Jose, CA, USA && 37 20 N 121 53 W && AIM erikmaxfrancis
    \__/ I will always remember / This moment
    -- Sade
    Erik Max Francis, Oct 2, 2004
    #5
  6. Lonnie Princehouse

    Paul Rubin Guest

    (Michele Simionato) writes:
    > Nevertheless, it is possible that if we had resumable exceptions we
    > could use them as a control flow structure in non-exceptional situations.
    > One could speculate about the idea ...


    Sure. You could raise a resumable exception whose handler runs some
    code before resuming after the exception. The handling code could do
    some stuff that raises its own resumable exception. Now you have two
    resumable exceptions pending, and it would be cool if you could resume
    the first one before resuming the second. In fact what you'd really
    like is a "resumption" object created by raising the exception, that
    you can pass control to at any time, sort of like yielding from a
    generator. Maybe you're getting deja vu now, since this is basically
    what Stackless Python continuations were. They give you a simple way
    to implement coroutines and just about anything else you could want.
    Paul Rubin, Oct 2, 2004
    #6
  7. Lonnie Princehouse

    Paul Foley Guest

    On 1 Oct 2004 12:52:38 -0700, Lonnie Princehouse wrote:

    > In a recent post, Michele Simionato asked about resumable (or
    > re-entrant) exceptions, the basic idea being that when raised and
    > uncaught, these exceptions would only propagate backwards through a
    > limited number of frames before being implicitly ignored. Alex


    What a strange idea.

    > Nonetheless, I tried to write some demo code that implemented
    > resumable exceptions, but ran face-first into a brick wall: I
    > couldn't find any way to manipulate the call stack (to execute code in
    > a frame other than the current one)


    The mistake you're making is to conflate Python's exceptions with the
    resumable exceptions you're trying to implement. Python exceptions
    are more like Common Lisp's catch/throw mechanism (sort of a
    dynamically scoped "goto") than they are like the condition system.
    You can use Python's exception mechanism for the primitive control
    transfer, and build something on top of that (but since you can't
    write syntax in Python it's going to be butt-ugly). That's what Shai
    Berger was trying to do.

    Keep a list of (exception-type, function) pairs. Where you want a
    try/except, write a try/finally instead, with the "try" part pushing
    "except" handlers on the front of this list, and the "finally" part
    taking them back off (to emulate dynamic binding...don't use threads).
    Instead of using raise, look up the exception type in this list and
    call the associated function, so it runs above the failure point in
    the call stack (but note that it has to transfer control somewhere
    else if you don't want to return). For restarts, do a similar thing,
    mapping restart names to ("randomly" named) exception subclasses (as
    catch tags); where you want a restart, write try/except using that
    subclass name, push it on the restarts list, and to invoke it look up
    the name and use raise on the tag. Or something.

    --
    Malum est consilium quod mutari non potest -- Publilius Syrus

    (setq reply-to
    (concatenate 'string "Paul Foley " "<mycroft" '(#\@) "actrix.gen.nz>"))
    Paul Foley, Oct 2, 2004
    #7
  8. Re: Exception feature creep! (was: re-entering in the normal flowafter an exception is raised)

    Michele Simionato ha scritto:


    > Nevertheless, it is possible that if we had resumable exceptions we
    > could use them as a control flow structure in non-exceptional situations.
    > One could speculate about the idea ...
    >


    I have the feeling I don't have an use for resumable exceptions mainly
    because I was never exposed to the them.
    Kind of a blub paradox.



    I wonder if StacklessPython can handle this.
    Resumable Exceptions are really easy to do if you can grab the current
    continuation, but I seem to remember conts were banned from the
    stackless world.
    gabriele renzi, Oct 2, 2004
    #8
  9. (Michele Simionato) wrote in message news:<>...
    >
    > Well, actually that is NOT what I asked. Erik Max Francis got my point:
    >


    Indeed! I seem to have completely misinterpreted your post!

    At least it.. raised.. some interesting conjecture about exceptions.
    I wonder if yield could be abused to simulate resumable exceptions
    under certain situations?

    class ResumableException(Exception): pass

    def foo():
    if something_has_gone_wrong():
    yield ResumableException
    print "Resumed!"


    result = foo()
    if result is ResumableException:
    if recovery_is_possible():
    foo()
    else:
    raise result

    Far from ideal, but it is a way of suspending and then resuming
    execution. It does have the unfortunate caveat that the caller needs
    to be aware of what's coming, which sort of defeats the point of
    exceptions. A kind of homage to the things people do in languages
    that lack exception-handling mechanisms...
    Lonnie Princehouse, Oct 2, 2004
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. davidw
    Replies:
    3
    Views:
    403
    Curt_C [MVP]
    Aug 27, 2004
  2. Michele Simionato
    Replies:
    7
    Views:
    341
    Alex Martelli
    Sep 29, 2004
  3. Jack Dowson
    Replies:
    0
    Views:
    441
    Jack Dowson
    May 7, 2007
  4. Guest
    Replies:
    1
    Views:
    149
    Brock Allen
    May 25, 2005
  5. mjkahn

    DLLHOST and memory creep

    mjkahn, May 13, 2005, in forum: ASP General
    Replies:
    0
    Views:
    122
    mjkahn
    May 13, 2005
Loading...

Share This Page