[Tutor] best practice: throw exception or set a flag?

Steven D'Aprano steve at pearwood.info
Fri Feb 4 03:11:52 CET 2011


Alex Hall wrote:
> Hi all,
> I am wondering what the best way to do the following would be: throw
> an exception, or always return an object but set an error flag if
> something goes wrong? 

Raise an exception. Error flags are an anti-pattern -- a software idiom 
that you should not follow.

The problem with flags is that callers will forget to check them, which 
leads to problems being revealed far away from where the problem was 
caused. That makes it *really* hard to debug.

result = function(x)  # fails and sets an error flag in result
do_something_else()
data = [1, 2, 'a', result, 'xyz']  # store
another_function(data)
# ...
# ...
# lots more code here
# ...
# ...
x = data[3]
do_something_with(x)

which then blows up, because x is invalid but you haven't checked the 
error flag. The problem actually was with the *original* x, all the way 
back at the start, but that's been thrown away now, never to be seen 
again, which makes it hard to debug why it failed.

A million, billion, trillion times worse is if you have a single global 
error flag! That's *disastrous*, because you MUST check the flag 
*immediately*, otherwise it can be cleared.

x = function(100000000)  # fails
y = another_function(1000)
if global_error_flag:
     # seems to be safe to use x
     process(x)  # but it isn't, and this blows up

the problem being that another_function makes a second call to 
function(), only this one succeeds and resets the global flag. If you do 
this, the ghost of a thousand programmers will drag your spirit off to 
the nether regions of Hell, where you will have to debug the Windows 
kernel using only the `ed` editor on a keyboard missing the letters "x", 
"s" and "1" for all of eternity.

For those who don't know the `ed` editor, it is "the standard Unix editor":

http://www.gnu.org/fun/jokes/ed.msg.html



> Which is the "standard" way when dealing with objects? Throw
> exceptions or always return an object, even if said object has an
> error and may therefore not have data beyond an error code and
> message? If I go the exception route, can I somehow put a message into
> the exception, maybe adding it as an attribute of my custom exception
> class? I assume so...
> except e:
>  print e.message

Most standard is to raise an exception. The syntax is:

raise ValueError("any message you like")

or use whatever error type suits your problem. You can even define your 
own exception types:

class MyError(ValueError):
     pass


Less common, but still reasonable, is to raise an error sentinel in 
place of the normal result. For example, re.match() and re.search() 
return None when there is nothing found, instead of a MatchObject. 
Another example, str.find() returns -1.

The disadvantage of this is obvious:

 >>> string = "Nobody expects the Portuguese Inquisition!"
 >>> offset = string.find("Spanish")
 >>> print(string[offset:])  # expecting "Spanish Inquisition!"
!


For special purposes, like mathematics, you can define error values that 
propagate through calculations. Python has half-hearted support for 
such "Not A Number" codes:

 >>> nan = float('nan')
 >>> nan + 1  # doesn't fail, but propagates
nan
 >>> nan**2
nan
 >>> nan - 1000
nan

as well as infinity. But you should consider this a very specialized 
solution (as well as a lot of work!!!).

Another non-standard solution is to return a pair of values, a flag plus 
the value you actually want:

flag, value = function(10000)
if flag:
     do_something_with(value)
else:
     process_error()



> or something like that. I know I have research to do about the
> specifics of all this, but before I go off and look it all up I am
> wondering if it is the best way to go as far as standards and best
> coding practices. This is still that api wrapper, so I am not the only
> one who may end up using this file and I want to make it into
> something that is useable and does what people expect. TIA.

Then there is absolutely not even a shadow of a doubt: use exceptions.



-- 
Steven



More information about the Tutor mailing list