Exceptions as efficient programming
Python likes to make programming efficient: that is, to make programs fast and easy to write, and eliminate the tedious drudgery. Pretty much all dynamically typed languages do, since static typing is a lot of effort (except in languages with a lot of type inference, where it is only some effort).
After writing yesterday's entry, it's struck me that exceptions are a form of efficient programming, because they let you aggregate error checking and error handling across a large block of code.
Without exceptions, proper error checking means a lot of tedious code to check each possibly failing operation and handle the errors. Usually the code is identical or almost identical, making the tedium more pronounced. (This tedium is one reason why people can wind up skipping some error checks.)
With exceptions, you only write new code when you want to do something differently on an error. Otherwise, you can cover a large swatch of code, full of various calls that may fail, with just one exception and just one block of code to handle the problem. (Especially if you let fine details of what went wrong for error messages be captured in the exception or in ongoing state variables.)
Result: less tedium, more efficiency, happier programmers, and Python helps one of its goals along again.
Exceptions and casual programming
Exceptions have somewhat of a bad reputation in serious programming circles. People feel that they are troublesome for various reasons, including that they are non-local gotos and they make it hard to guarantee that you really are cleaning up after problems. (You can find posts about this at Joel on Software and in Raymond Chen's blog, among other places.)
I don't know about that, but I do know that exceptions are really good for casual programs, which is what I mostly write. Casual programs is my label for the small and narrow-scope utilities that crop up all over system administration. Shell scripts, perl and Python programs of a few hundred lines at most, and so on.
I like exceptions for casual programs because they mean that blind optimism and blithe ignorance of potential system-level problems is not an option. Either I explicitly write code to handle a problem like an IO error, or my program aborts with a stack puke and I find out about it.
Exceptions force you to deal with errors. You may not deal with them well, but you do not get to tacitly ignore them. (You can explicitly ignore them, sometimes semi-accidentally as I mentioned in BroadTrys. Solution: don't do that.)
In theory, serious industrial-strength programs are written to carefully check everything that can go wrong and handle all of the errors. However, even if the theory actually was the reality, casual programs are not written that way; either because the authors don't know better, or because they consider it too much nit-picking work for the expected gains.
This is one reason I've come to really like Python for casual programs (as annoying as exceptions sometimes are to deal with). They're also a useful security backstop; many security exposures are created by failing to notice bad conditions, buffer overflows being the classical example.