raise None

Chris Angelico rosuav at gmail.com
Wed Dec 30 21:12:37 EST 2015


On Thu, Dec 31, 2015 at 12:26 PM, Steven D'Aprano <steve at pearwood.info> wrote:
> Traceback (most recent call last):
>   File "spam", line 19, in this
>   File "spam", line 29, in that
>   File "spam", line 39, in other
> ThingyError: ...
>
>
> I think this is a win for debuggability. (Is that a word?) But it's a bit
> annoying to do it today, since you have to save the return result and
> explicitly compare it to None. If "raise None" was a no-op, it would feel
> more natural to just say raise _validate() and trust that if _validate
> falls out the end and returns None, the raise will be a no-op.

(Yes, it is.)

Gotcha. So here's an alternative possibility. Instead of raising None
doing nothing, what you really want is to have _validate signal an
error with one less level of traceback - that is, you want it to raise
an exception from the calling function.

class remove_traceback_level:
    def __enter__(self): return self
    def __exit__(self, type, value, traceback):
        if type is None: return
        tb = traceback
        while tb.tb_next: tb = tb.tb_next
        tb.tb_next = None
        raise value from traceback

def _validate(a, b):
    with remove_traceback_level():
        if condition(a) or condition(b): raise TypeError
        if other_condition(a) or something_else(b): raise ValueError
        if whatever(a): raise SomethingError


The trouble is that this doesn't actually work, because tb_next is
read-only. But is there something along these lines that would make a
function raise exceptions as if it were in another function?

ChrisA



More information about the Python-list mailing list