How to effectively use exception

Carl Banks idot at vt.edu
Sat Apr 14 15:39:49 EDT 2001


Steven Haryanto <steven at haryan.to> wrote:
> So far I have understood one rule of thumb about exceptions:
> "Catch as few of them as possible in the inner blocks of the
> program. The uncaught exceptions will creep up to the upper
> blocks until, at one level, it will be caught by the code that
> know how to handle it. The main block should catch all the
> rest and act accordingly.

I prefer this rule of thumb: "The exeption should be handled whereever
the program can logically proceed after the exception is raised."

So if the exception is a fatal error, the only place I would handle it
is at the very top.

Sometimes a program can proceed logically from the point where the the
exception occured; there is no reason at all to artificially move up
the try block in this case.  For example, suppose a program logic is
this: if a file exists, open and parse it; if not, do nothing.  In
such a case, I would have no guilt at all about doing this:

try:
	f = open (filename, 'r')
	parse_file (f)
	f.close ()
except IOError:
	pass

Now, suppose that the file parser involves deep recursion, and if it
encounters a syntax error (in the file, not in the Python program), it
completely abandons the parse by raising UserSyntaxError.  Where
should UserSyntaxError be caught?  Well, since the parse was
abandoned, the exception should be handled by the caller of
parse_file.  So I would add the following except block to the try
block above:
	
except UserSyntaxError, v:
	f.close()
	error ("Syntax Error", v.line, v.column)

Of course, it's possible that, for some other reason, the program
might be not able to proceed logically here.  For example, the syntax
error could turn out to be fatal, in which case the only place to
handle it would be at the very top.


> There are two things that I seek advice on:
> 
> First, should we use exceptions whenever possible? For example,
> should a smallish function that do some testing return 1/0 to
> indicate success/failure or should it raise ValueError if the
> test fails? Is the try-except-else style more Pythonic/
> recommended than the if-else-then style? If not, what are the
> considerations to balance the two?

You describe your smallish function as testing for success/failure.
To me, "failure" means that something happens which wouldn't have
happened in the ideal universe.  Failure means something is
interfering with your program.  If that's what your function tests
for, then I advise using an exception.

If your smallish function tests some condition, where either result is
legal and doesn't interfere with the program, then I would normally
return 1/0.

If your smallish test function does not normally test for failure, but
in a particular context, a certain result does indicate failure, I
would raise the exception in the calling function, not in the smallish
test function.

I suppose a good rule of thumb here is to ask yourself, simply, "Is it
an exception?"


> Second, when do we create our own specific Exception classes,
> and when do we just use the existing standard Exception (I use
> ValueError in a lot of my methods & functions, accompanied by
> the specific message string. So far I haven't faced with the
> need to create a custom Exception class).

It seems to me that if you use the builtin exception exactly as it is
used by the language, it's ok.  You might want to review how the
exception is used by the language to make sure you're using it the
same way.

Then again, it seldom hurts to use own.  I would say, "When in
reasonable doubt, use your own."


> Lastly, can someone recommend some readings on this matter?

Hacker and philosopher, myself.  Can't help you too much here.


-- 
CARL BANKS

"What is life but a series of inspired follies?"
    -- Henry Higgins in _Pygmalion_, by George Bernard Shaw



More information about the Python-list mailing list