raise None

Cameron Simpson cs at zip.com.au
Wed Dec 30 23:03:20 EST 2015


On 31Dec2015 12:26, Steven D'Aprano <steve at pearwood.info> wrote:
>On Thu, 31 Dec 2015 11:38 am, Chris Angelico wrote:
>>> [... functions calling common _validate function ...]
>>> But when the argument checking fails, the traceback shows the error
>>> occurring in _validate, not eggs or spam. (Naturally, since that is where
>>> the exception is raised.) That makes the traceback more confusing than it
>>> need be.
>>
>> If the validation really is the same in all of them, then is it a
>> problem to see the validation function in the traceback? Its purpose
>> isn't simply "raise an exception", but "validate a specific set of
>> inputs". That sounds like a perfectly reasonable traceback line to me
>> (imagine if your validation function has a bug).
>
>Right -- that's *exactly* why it is harmful that the _validate function
>shows up in the traceback.

I think I'm still disagreeing, but only on this point of distinguishing 
_validate bug exceptions from _validate test failures.

>If _validate itself has a bug, then it will raise, and you will see the
>traceback:
>
>Traceback (most recent call last):
>  File "spam", line 19, in this
>  File "spam", line 29, in that
>  File "spam", line 39, in other
>  File "spam", line 5, in _validate
>ThingyError: ...
>
>which tells you that _validate raised an exception and therefore has a bug.

Ok....

>Whereas if _validate does what it is supposed to do, and is working
>correctly, you will see:
>
>Traceback (most recent call last):
>  File "spam", line 19, in this
>  File "spam", line 29, in that
>  File "spam", line 39, in other
>  File "spam", line 5, in _validate
>ThingyError: ...
>
>and the reader has to understand the internal workings of _validate
>sufficiently to infer that this exception is not a bug in _validate but an
>expected failure mode of other when you pass a bad argument.

Would it not be useful then to name the including function in the exception 
text?

>In the case where _validate *returns* the exception instead of raising it,
>and the calling function (in this case other) raises, you see this in the
>case of a bug in _validate:
>
>Traceback (most recent call last):
>  File "spam", line 19, in this
>  File "spam", line 29, in that
>  File "spam", line 39, in other
>  File "spam", line 5, in _validate
>ThingyError: ...
>
>and this is the case of a bad argument to other:
>
>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 confess that when I want to check several things I would like to return 
several failure indications. So thing on that line, how about this:

  for blam in _validate(a, b):
    raise blam

which leaves you open to gatheroing them all up instead of aborting on the 
first complaint.

>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.

This is a nice idea though. Succinct and expressive, though people would have 
to learn that:

  raise foo()

does not unconditionally abort at this point.

Cheers,
Cameron Simpson <cs at zip.com.au>



More information about the Python-list mailing list