[Tutor] How to anticipate and deal with unexpected exceptions (was: Is there a convenient table of Python 3.4 exceptions?)

Ben Finney ben+python at benfinney.id.au
Sat Oct 25 05:42:32 CEST 2014


boB Stepp <robertvstepp at gmail.com> writes:

> In the programs I have been dabbling in at work, I am often
> "surprised" by the situations my users stumble into that I did not
> have sufficient imagination to consider up front.

This is a good thing to focus on. Improving the robustness of your code
is a matter of experience, but you can learn from the experience (i.e.
mistakes) of the several decades of programmers who have come before
you, and the approaches that have arisen in response to those mistakes.

> And in line with your statements I have often wondered if I had done
> enough error checking, or whether in some instances I was doing too
> much.

It's interesting that you raise that dilemma. The Python style
definitely leans away from LBYL (Look Before You Leap, i.e. lots of
checking for errors before performing the task at hand), and much more
toward EAFP (it is Easier to Ask Forgiveness than Permission).

EAFP means that if you're going to perform a task in your code, you make
a clear clean API, document that API, and then trust that the other
programmers using that API will get the preconditions and parameters
correct. If they don't, allow errors to propagate all the way back to
that code and let the user of your API handle the errors.

So, when you're using the Python standard library, you're expected not
to know every possible error that can occur; but rather, to read and
understand the API you're writing to, and set appropriate preconditions
and parameters. If you don't, you can rely on getting an exception
object that tells you about the problem.

> Trying to imagine what the user might do is often a difficult
> exercise, especially as my programs have been becoming more lengthy
> and complex. I suppose this gets easier with more knowledge and
> experience?

It also gets easier if you record every bug-fix as a unit test, and
automate a full run of all the existing unit tests after changing your
program behaviour. That way, you:

* Don't have to keep re-discovering bugs you thought you'd fixed.

* Continually ratchet up the robustness of your code.

* Never get to the point where you feel like you can't trust the old
  code.

* Begin to internalise the habit of anticipating what possible
  conditions you should test for, and write those tests *first*.

Once you're comfortable with always writing a battery of unit tests for
any change you make, and accumulating a suite of unit tests that run
before every release (and ideally much more often than that), and never
release any code that breaks any of the tests, you will gain a
confidence in making changes that is priceless.

-- 
 \      “Very few things happen at the right time, and the rest do not |
  `\     happen at all. The conscientious historian will correct these |
_o__)                          defects.” —Mark Twain, _A Horse's Tale_ |
Ben Finney



More information about the Tutor mailing list