2 added 1592 characters in body
source | link

I think this argumentstatement is extremely misleadingtrue only in very specific circumstances - where you don't care if the output is correct. Exceptions

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 (in Pythonas a developer) will occur whethercannot, or not you used try /don't want to, deal with.

Your example, however, is about exceptcatching exceptions. So ifIf you wrote your own error checkcatch an exception, anythingyou're not protecting yourself from scenarios you forgot about would still raise an exception;might have overlooked. You are doing precisely the opposite: you just won't catch itassume that you haven't overlooked any scenario that might have caused this type of exception, and sotherefore you're confident that it's alright to catch it (and thus prevent it from causing the program willto exit, as any uncaught exception would).

TheUsing the exception approach, if you see try/exceptValueError exception, you skip a line. Using the traditional non-exception approach from, you count the original example doesnumber of returned values from not make the program safer at all; it makes it more dangeroussplit, as you'll be continuing execution whenand if it's less than 2, you skip a line. Should you feel more secure with the exception occurred. That decision to continue execution will be based on assumingapproach, since you know what happened basedmay have forgotten some other "error" situations in your traditional error check, and except ValueError would catch them for you?

This depends on the exception type you've seennature of your program.

ForIf you're writing, for example, what doesa 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 except ValueError mean?, 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 maymight think it's obvious it canthat the only be caused byway you can see ValueError in this code, is if split returning insufficient elementsreturned only one value (instead of two). But what if your printprint statement useslater starts using an expression that raises ValueError under some conditions? This will cause you to skip some lines not because they miss :, but because they make your print calls raise the same type of exceptionfails on them. This "silent bug" would be extremely hard to detect and then to debug.

For this reason, I have strong reservations about the Pythonic approach of "EAFP", unless there is no other way to achieve the desired result. Foran example, exceptions are nearly unavoidable to open a file in of a multisubtle bug I was referring to earlier -threaded environment you would not notice anything, just lose some lines.

Some additional comments:

As pointed out by others, bare exceptMy recommendation is very bad. Luckily, the code providedto avoid catching (but not raising!) exceptions in the questioncode where producing incorrect output is not the final version from the bookworse than exiting. At the next stepThe only time I'd catch an exception in such code is when I have a truly trivial expression, the book guides the student to use except ValueError insteadso I can easily reason what may cause each of the bare exceptpossible exception types.

TheAs to the performance impact of using exceptions, it is trivial (in Python) won't be material unless exceptions are encountered frequently.

But ifIf 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 returnedraised (which happens only after the remote server parses your command and finds a problem with it). Obviously, the former is orders of magnitude faster - but it only matters if you frequently send malformed command strings to remote servers.

  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 except.

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.

I think this argument is extremely misleading. Exceptions (in Python) will occur whether or not you used try / except. So if you wrote your own error check, anything you forgot about would still raise an exception; you just won't catch it, and so the program will exit.

The try/except approach from the original example does not make the program safer at all; it makes it more dangerous, as you'll be continuing execution when the exception occurred. That decision to continue execution will be based on assuming you know what happened based on the exception type you've seen.

For example, what does except ValueError mean? You may think it's obvious it can only be caused by split returning insufficient elements. But what if your print statement uses an expression that raises ValueError under some conditions? This will cause you to skip some lines not because they miss :, but because they make your print calls raise the same type of exception. This "silent bug" would be extremely hard to detect and then to debug.

For this reason, I have strong reservations about the Pythonic approach of "EAFP", unless there is no other way to achieve the desired result. For example, exceptions are nearly unavoidable to open a file in a multi-threaded environment.

Some additional comments:

As pointed out by others, bare except is very bad. Luckily, the code provided in the question is not the final version from the book. At the next step, the book guides the student to use except ValueError instead of the bare except.

The performance impact of using exceptions (in Python) won't be material unless exceptions are encountered frequently.

But if you 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 returned (which happens after the remote server parses your command and finds a problem with it). Obviously, the former is orders of magnitude faster - but it only matters if you frequently send malformed command strings to remote servers.

  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.

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 except.

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.

1
source | link

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 argument is extremely misleading. Exceptions (in Python) will occur whether or not you used try / except. So if you wrote your own error check, anything you forgot about would still raise an exception; you just won't catch it, and so the program will exit.

The try/except approach from the original example does not make the program safer at all; it makes it more dangerous, as you'll be continuing execution when the exception occurred. That decision to continue execution will be based on assuming you know what happened based on the exception type you've seen.

For example, what does except ValueError mean? You may think it's obvious it can only be caused by split returning insufficient elements. But what if your print statement uses an expression that raises ValueError under some conditions? This will cause you to skip some lines not because they miss :, but because they make your print calls raise the same type of exception. This "silent bug" would be extremely hard to detect and then to debug.

For this reason, I have strong reservations about the Pythonic approach of "EAFP", unless there is no other way to achieve the desired result. For example, exceptions are nearly unavoidable to open a file in a multi-threaded environment.

Some additional comments:

As pointed out by others, bare except is very bad. Luckily, the code provided in the question is not the final version from the book. At the next step, the book guides the student to use except ValueError instead of the bare except.

The performance impact of using exceptions (in Python) won't be material unless exceptions are encountered frequently.

But if you 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 returned (which happens after the remote server parses your command and finds a problem with it). Obviously, the former is orders of magnitude faster - but it only matters if you frequently send malformed command strings to remote servers.

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.