Skip to main content
Expanded some points.
Source Link
Steve Barnes
  • 5.3k
  • 1
  • 18
  • 19

NO! - not in general - exceptions are not considered good flow control practice with the exception of single class of code.

There are a couple of reasons why, in the high reliability & testing worlds at least, exceptions for flow control are not considered a good idea:

  1. Exceptions can potentially occur anywhere not just at a return point and may be occurring deep in nested functions.
  2. If you are using exceptions to return from function calls then you may end up catching too generally and masking real errors. Consider a maths array function that can raise more than one type of exception to signal that it has finished - if your code uses except Exception: to detect this then divide by zero errors and bounds errors will also be caught as a "Finished" flag.

The one place where exceptions are considered a reasonable, or even better, way to signal a condition is generator or iterator operations. These operations can return any possible value as a valid result so a mechanism is needed to signal a finish.

with open(source, 'rb') as inputinput_file: for val in inputinput_file.readbyte(): # This line will raise a StopIteration exception an call input.__exit__() processbyte(val) # Not called if there is nothing read 

This hidden use of exceptions is a lot easier to read and comprehend for most people.

I strongly urge you to read PEP 343 which gives the background, rationale, examples, etc.

It is also usual to use an exception to signal the end of processing when using generator functions to signal the finish. Again this is nicely hidden from you when you use:

for value in generator_funcion(): do_something_with(value) # Carry on now that you have finished 

I would like to add that your searcher example is almost certainly backwards, such functions should be generators, returning the first match on the first call, then substituent calls returning the next match, and raising a NotFound exception when there are no more matches.

Note that these hidden exception uses are using very specific exceptions so that any other exceptions will still be visible. The reason why these hidden exception classes are documented as such is that you may have reasons to override them e.g. if you are reading from a serial port or other device that can sometimes not have a value ready but hasn't actually finished you can deal with this.

NO! - not in general - exceptions are not considered good flow control practice with the exception of single class of code. The one place where exceptions are considered a reasonable, or even better, way to signal a condition is generator or iterator operations. These operations can return any possible value as a valid result so a mechanism is needed to signal a finish.

with open(source) as input: for val in input.readbyte(): # This line will raise a StopIteration exception an call input.__exit__() processbyte(val) # Not called if there is nothing read 

I strongly urge you to read PEP 343 which gives the background, rationale, examples, etc.

It is also usual to use an exception to signal the end of processing when using generator functions to signal the finish.

I would like to add that your searcher example is almost certainly backwards, such functions should be generators, returning the first match on the first call, then substituent calls returning the next match, and raising a NotFound exception when there are no more matches.

NO! - not in general - exceptions are not considered good flow control practice with the exception of single class of code.

There are a couple of reasons why, in the high reliability & testing worlds at least, exceptions for flow control are not considered a good idea:

  1. Exceptions can potentially occur anywhere not just at a return point and may be occurring deep in nested functions.
  2. If you are using exceptions to return from function calls then you may end up catching too generally and masking real errors. Consider a maths array function that can raise more than one type of exception to signal that it has finished - if your code uses except Exception: to detect this then divide by zero errors and bounds errors will also be caught as a "Finished" flag.

The one place where exceptions are considered a reasonable, or even better, way to signal a condition is generator or iterator operations. These operations can return any possible value as a valid result so a mechanism is needed to signal a finish.

with open(source, 'rb') as input_file: for val in input_file.readbyte(): # This line will raise a StopIteration exception an call input.__exit__() processbyte(val) # Not called if there is nothing read 

This hidden use of exceptions is a lot easier to read and comprehend for most people.

I strongly urge you to read PEP 343 which gives the background, rationale, examples, etc.

It is also usual to use an exception to signal the end of processing when using generator functions to signal the finish. Again this is nicely hidden from you when you use:

for value in generator_funcion(): do_something_with(value) # Carry on now that you have finished 

I would like to add that your searcher example is almost certainly backwards, such functions should be generators, returning the first match on the first call, then substituent calls returning the next match, and raising a NotFound exception when there are no more matches.

Note that these hidden exception uses are using very specific exceptions so that any other exceptions will still be visible. The reason why these hidden exception classes are documented as such is that you may have reasons to override them e.g. if you are reading from a serial port or other device that can sometimes not have a value ready but hasn't actually finished you can deal with this.

Change Found to Not Found
Source Link
Steve Barnes
  • 5.3k
  • 1
  • 18
  • 19

NO! - not in general - exceptions are not considered good flow control practice with the exception of single class of code. The one place where exceptions are considered a reasonable, or even better, way to signal a condition is generator or iterator operations. These operations can return any possible value as a valid result so a mechanism is needed to signal a finish.

Consider reading a binary file of stream one byte at a time - absolutely any value is a potentially valid result but we still need to signal an end of file. So we have a choice, return two values, (the byte value & a valid flag), every time or raise an exception when there is no more to do. In the two cases the consuming code can look like:

# Using validity flag valid, val = readbyte(source) while valid: processbyte(val) valid, val = readbyte(source) tidy_up() 

alternatively:

# With exceptions try: val = readbyte(source) processbyte(val) # Note if a problem occurs here it will also raise an exception except Exception: # Use a specific exception here! tidy_up() 

But this has, since PEP 343 was implemented & back ported, all been neatly wrapped up in the with statement. The above becomes, the very pythonic:

with open(source) as input: for val in input.readbyte(): # This line will raise a StopIteration exception an call input.__exit__() processbyte(val) # Not called if there is nothing read 

In python3 this became:

for val in open(source, 'rb').read(): processbyte(val) 

I strongly urge you to read PEP 343 which gives the background, rationale, examples, etc.

It is also usual to use an exception to signal the end of processing when using generator functions to signal the finish.

I would like to add that your searcher example is almost certainly backwards, such functions should be generators, returning the first match on the first call, then substituent calls returning the next match, and raising a NotFound exception when there are no more matches.

NO! - not in general - exceptions are not considered good flow control practice with the exception of single class of code. The one place where exceptions are considered a reasonable, or even better, way to signal a condition is generator or iterator operations. These operations can return any possible value as a valid result so a mechanism is needed to signal a finish.

Consider reading a binary file of stream one byte at a time - absolutely any value is a potentially valid result but we still need to signal an end of file. So we have a choice, return two values, (the byte value & a valid flag), every time or raise an exception when there is no more to do. In the two cases the consuming code can look like:

# Using validity flag valid, val = readbyte(source) while valid: processbyte(val) valid, val = readbyte(source) tidy_up() 

alternatively:

# With exceptions try: val = readbyte(source) processbyte(val) # Note if a problem occurs here it will also raise an exception except Exception: # Use a specific exception here! tidy_up() 

But this has, since PEP 343 was implemented & back ported, all been neatly wrapped up in the with statement. The above becomes:

with open(source) as input: for val in input.readbyte(): # This line will raise a StopIteration exception an call input.__exit__() processbyte(val) 

I strongly urge you to read PEP 343 which gives the background, rationale, examples, etc.

NO! - not in general - exceptions are not considered good flow control practice with the exception of single class of code. The one place where exceptions are considered a reasonable, or even better, way to signal a condition is generator or iterator operations. These operations can return any possible value as a valid result so a mechanism is needed to signal a finish.

Consider reading a binary file of stream one byte at a time - absolutely any value is a potentially valid result but we still need to signal an end of file. So we have a choice, return two values, (the byte value & a valid flag), every time or raise an exception when there is no more to do. In the two cases the consuming code can look like:

# Using validity flag valid, val = readbyte(source) while valid: processbyte(val) valid, val = readbyte(source) tidy_up() 

alternatively:

# With exceptions try: val = readbyte(source) processbyte(val) # Note if a problem occurs here it will also raise an exception except Exception: # Use a specific exception here! tidy_up() 

But this has, since PEP 343 was implemented & back ported, all been neatly wrapped up in the with statement. The above becomes, the very pythonic:

with open(source) as input: for val in input.readbyte(): # This line will raise a StopIteration exception an call input.__exit__() processbyte(val) # Not called if there is nothing read 

In python3 this became:

for val in open(source, 'rb').read(): processbyte(val) 

I strongly urge you to read PEP 343 which gives the background, rationale, examples, etc.

It is also usual to use an exception to signal the end of processing when using generator functions to signal the finish.

I would like to add that your searcher example is almost certainly backwards, such functions should be generators, returning the first match on the first call, then substituent calls returning the next match, and raising a NotFound exception when there are no more matches.

Source Link
Steve Barnes
  • 5.3k
  • 1
  • 18
  • 19

NO! - not in general - exceptions are not considered good flow control practice with the exception of single class of code. The one place where exceptions are considered a reasonable, or even better, way to signal a condition is generator or iterator operations. These operations can return any possible value as a valid result so a mechanism is needed to signal a finish.

Consider reading a binary file of stream one byte at a time - absolutely any value is a potentially valid result but we still need to signal an end of file. So we have a choice, return two values, (the byte value & a valid flag), every time or raise an exception when there is no more to do. In the two cases the consuming code can look like:

# Using validity flag valid, val = readbyte(source) while valid: processbyte(val) valid, val = readbyte(source) tidy_up() 

alternatively:

# With exceptions try: val = readbyte(source) processbyte(val) # Note if a problem occurs here it will also raise an exception except Exception: # Use a specific exception here! tidy_up() 

But this has, since PEP 343 was implemented & back ported, all been neatly wrapped up in the with statement. The above becomes:

with open(source) as input: for val in input.readbyte(): # This line will raise a StopIteration exception an call input.__exit__() processbyte(val) 

I strongly urge you to read PEP 343 which gives the background, rationale, examples, etc.