[Tutor] Terminology question
Steven D'Aprano
steve at pearwood.info
Sat May 16 08:04:17 CEST 2015
On Thu, May 14, 2015 at 03:43:30PM -0700, Jim Mooney Py3.4.3winXP wrote:
> I noticed that if I call a function that throws an error, I can catch it
> from the caller, instead of catching it in the function. Is this is what is
> known as "errors bubbling up?" Also, is this how you're supposed to do it?
Consider a chain of functions:
main() calls setup();
setup() calls process_arguments();
process_arguments() calls read_config();
read_config() calls open("somefile");
and open("somefile") raises an exception (perhaps the file cannot be
found, or you don't have permission to read it).
Each function in the chain gets a chance to catch the exception:
open <- read_config <- process_arguments <- setup <- main
If open doesn't catch the exception, we say that the exception "bubbles
up" the chain until it is caught, or if none of them catch it, then it
bubbles all the way up and finally reaches the Python interpreter, which
prints a stack trace and exits.
[...]
> def get_input():
> inp = input("Enter minimum, maximum, rows, and columns, separated by
> commas: ")
> inps = inp.split(',')
> try:
> minimum = int(inps[0])
> maximum = int(inps[1])
> rows = int(inps[2])
> columns = int(inps[3])
> return minimum, maximum, rows, columns
This is not best practice. There are too many things which might cause
an exception. Ideally, a try block should only contain *one* thing which
might go wrong. Here you have at least four. By treating them all the
same, you lose the opportunity to give the user information about
*which* one they screwed up.
> except ValueError as err:
> print("non-integer entered", err)
> return None
This is bad practice, for two reasons.
You might not think so yet, but Python tracebacks give you a lot of
useful debugging information. Here, you flush that useful information
down the toilet and replace it with a not-very helpful message
"non-integer entered" (plus a bit more stuff). In a trivial script that
might not matter, but in a big script, you may have *no idea* where this
non-integer was entered. There could be thirty places where it might
happen. How do you know which one it is?
The second reason is that you really should only catch exceptions that
you can do something about. If you can't fix the problem, there's no
point in catching the exception[1]. In this case, if the user doesn't
enter a valid set of values, there's no way you can proceed. So why
bother delaying the inevitable? Just let the exception exit the program.
This will also look after all the little things which distinguish a
professional quality application from a jerry-built beginner's toy. For
example: error messages should print to stderr, not stdout; the
application should exit with a non-zero result code. If this means
nothing to you, don't be too concerned about it, just understand that
Python will do the right thing provided you don't get in its way, as you
just did by catching the exception.
[1] Well, there is one other reason: in an application aimed at
non-programmers, you might choose to catch the exception, log the
traceback somewhere where you can get to it for debugging, and display a
"friendly" (i.e. non-technical, non-threatening, useless) message to the
user. But as a beginner yourself, you shouldn't do this until you have
become an expert in reading tracebacks. Otherwise you're just hiding
debugging info that you need.
--
Steve
More information about the Tutor
mailing list