What's the best way to minimize the need of run time checks?

Steven D'Aprano steve+comp.lang.python at pearwood.info
Wed Aug 10 02:47:15 EDT 2016


On Wednesday 10 August 2016 15:20, Juan Pablo Romero Méndez wrote:

> Ok, so you suggested 1) catching exceptions at the point where you care, 2)
> preemptively check for certain runtime conditions to avoid exceptions 3)
> write as many tests as possible  4) learn to live with runtime errors.
> 
> Is that a fair characterization?

(1) Not quite.

Only catch exceptions you expect and *can deal with*. By deal with, I mean 
either recover from, or convert to a user-friendly error message (perhaps 
displaying it in a dialog for GUI apps).

Your script or application may want to use a top-level exception handler to 
catch any *unexpected* exceptions, log them, perform any extra cleanup needed, 
and display a nice error message before exiting. But that counts as gold-
plating: for many applications or scripts, aimed at technical or semi-technical 
users, its acceptable to just let the traceback print and the interpreter exit.

(2) Sometimes. Its a judgement call whether it is better to "Look Before You 
Leap" or "Easier To Ask For Forgiveness Rather Than Permission". It depends on 
what you are doing, how often you expect an exceptional case, the performance 
implications, whether there is a risk of "Time Of Check To Time Of Use" bug, 
etc. In other words, that's usually a technical question, not a matter of 
style.

Google for LBYL versus EAFP for more discussion.

Occasionally it comes down to both being equally good, in which case you get to 
pick whichever you like.

(3) Yes, this is correct.

Basically, with a dynamically-typed language like Python, you have to write all 
the tests you would write with a statically-typed language, plus some more. 
There's no question that the cost of the freedom dynamic typing gives you is 
that you have to write extra tests. But not as many as you might think.

The major differences in mindset between dynamic/static typing are:

- Where the compiler would detect a type error at compile time, you get the 
same result with a small unit test that checks for TypeError or AttributeError 
instead.

(Although see also the MyPy project, which brings an optional static type-
checker to Python.)

- As much as possible, avoid thinking "I need a list", and instead think "I 
need anything which offers the list interface". (Duck-typing.)

That *especially* counts for writing library code, application code you can be 
a bit more strict about types because you're only limiting yourself, not other 
users.

- A Python runtime exception is not like a segmentation fault. Its not going to 
overflow a buffer and execute random code. It's a controlled failure, not an 
uncontrolled one.

(4) There's no necessary reason to expect that you'll get more runtime errors 
in a well-written and tested Python application than you get in a well-written 
and tested C application.

Regardless of the language, you have to deal with runtime errors:

- network is down;
- disk is full;
- user lacks permission to edit that file;
- database error;
- account not found;

etc. Python is no different. And regardless of the language, the compiler can't 
check that "add_account" actually adds the account, you need a unit-test to 
check that. So you have to write tests either way.

Basically, just relax -- static type checks aren't useless, but they do very 
little that a runtime exception won't give you. So long as you have a good 
suite of unit tests that exercises the whole program, you'll find your type 
errors when they raise TypeError, then you fix them.

You may be gathering from this that dynamic typing and Test Driven Development 
go hand in hand. That's exactly right. They complement each other very well.



-- 
Steve




More information about the Python-list mailing list