The book's main argument is that the exception version of the code is better because it will catch anything that you might have overlooked if you tried to write your own error checking.
I think this statement is true only in very specific circumstances - where you don't care if the output is correct.
There is no doubt that raising exceptions is a sound and safe practice. You should do so whenever you feel there's something in the current state of the program that you (as a developer) cannot, or don't want to, deal with.
Your example, however, is about catching exceptions. If you catch an exception, you're not protecting yourself from scenarios you might have overlooked. You are doing precisely the opposite: you assume that you haven't overlooked any scenario that might have caused this type of exception, and therefore you're confident that it's alright to catch it (and thus prevent it from causing the program to exit, as any uncaught exception would).
Using the exception approach, if you see
ValueError exception, you skip a line. Using the traditional non-exception approach, you count the number of returned values from
split, and if it's less than 2, you skip a line. Should you feel more secure with the exception approach, since you may have forgotten some other "error" situations in your traditional error check, and
except ValueError would catch them for you?
This depends on the nature of your program.
If you're writing, for example, a web browser or a video player, a problem with inputs should not cause it to crash with an uncaught exception. It's far better to output something remotely sensible (even if, strictly speaking, incorrect) than to quit.
If you're writing an application where correctness matters (such as business or engineering software), this would be a terrible approach. If you forgot about some scenario that raises
ValueError, the worst thing you can do is to silently ignore this unknown scenario and simply skip the line. That's how very subtle and costly bugs end up in software.
You might think that the only way you can see
ValueError in this code, is if
split returned only one value (instead of two). But what if your
print statement later starts using an expression that raises
ValueError under some conditions? This will cause you to skip some lines not because they miss
:, but because
print fails on them. This is an example of a subtle bug I was referring to earlier - you would not notice anything, just lose some lines.
My recommendation is to avoid catching (but not raising!) exceptions in the code where producing incorrect output is worse than exiting. The only time I'd catch an exception in such code is when I have a truly trivial expression, so I can easily reason what may cause each of the possible exception types.
As to the performance impact of using exceptions, it is trivial (in Python) unless exceptions are encountered frequently.
If you do use exceptions to handle routinely occurring conditions, you may in some cases pay a huge performance cost. For example, suppose you remotely execute some command. You could check that your command text passes at least the minimum validation (e.g., syntax). Or you could wait for an exception to be raised (which happens only after the remote server parses your command and finds a problem with it). Obviously, the former is orders of magnitude faster. Another simple example: you can check whether a number is zero ~10 times faster than trying to execute the division and then catching ZeroDivisionError exception.
These considerations only matter if you frequently send malformed command strings to remote servers or receive zero-valued arguments which you use for division.
Note: I assume you would use
except ValueError instead of the just
except; as others pointed out, and as the book itself says in a few pages, you should never use bare
Another note: the proper non-exception approach is to count the number of values returned by
split, rather than search for
:. The latter is far too slow, since it repeats the work done by
split and may nearly double the execution time.