Exceptional Exceptions().
python
ERROR:root:Caught an error
Traceback (most recent call last):
File "example-logging-exception.py", line 8, in
x = get_number()
File "example-logging-exception.py", line 5, in get_number
return int('foo')
ValueError: invalid literal for int() with base 10: 'foo'
Python developers are used to see Exceptions flying around.
Exceptions are awesome, each exception is accompaniated by stack trace and thanks to additional tools such as Sentry we can include complete context in log and see what exactly happened.
However exceptions are often misunderstood as control flow statements and must admit, it's way too easy to get such an idea and write code like:
POSSIBLE_RAINBOW_COLORS = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet']
def magic_rainbow_drawer(x, y):
for stripe in POSSIBLE_RAINBOW_COLORS:
draw_stripe(stripe, x, y)
def draw_stripe(stripe, x, y):
if x == y:
raise IncorrectLocationError('Rainbow can not start and end at same place')
if stripe not in POSSILBE_RAINBOW_COLORS:
raise IncorrectColorError('Not a rainbow color!')
This is oversimplified example illustrates rationale behind using exceptions to control flow.
When developing new applications or libraries we should think carefully about what kind of exception it could raise and especially which exceptions could end up in user hands.
Django Forms is great example of exceptions use: Forms validation is built around `ValidationError` class, however it's barely impossible for end application to get `ValidationError` in own context.