Thanks to all for the answers. Sounds like exceptions are most definitely the way to go, and I will definitely put them in. In fact, this should make the wrapper a bit cleaner since I am not constantly checking for errors in variables and returning empty objects. Besides, I wouldn't want my soul stolen by angry programmers and doomed to working on Windows, let alone kernel debugging... :) Now, if it were Android, there might be something to the idea.
On 2/3/11, Steven D'Aprano <[email protected]> wrote: > 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 > > _______________________________________________ > Tutor maillist - [email protected] > To unsubscribe or change subscription options: > http://mail.python.org/mailman/listinfo/tutor > -- Have a great day, Alex (msg sent from GMail website) [email protected]; http://www.facebook.com/mehgcap _______________________________________________ Tutor maillist - [email protected] To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
