Suppress Exceptions in Python
Intro
Before we start, I have to tell you that you should “never suppress exceptions silently”. As Zen of Python states:
|
|
It is a common case to perform an operation that is expected to fail sometimes, but should not interrupt the program, like throwing 500 internal server errors in a web application.
We have to handle these fails, errors carefully.
Let’s use a simple and dummy code snippet to explain.
def f(lst):
"""Dummy function to throw an error"""
result = lst[10]
print(f"{result = }")
return result
if __name__ == "__main__":
f(lst=list(range(10)))
If you run above code, you will get IndexError
with a traceback like below:
Traceback (most recent call last):
File "/tmp/show/show.py", line 21, in <module>
f(lst=list(range(10)))
File "/tmp/show/show.py", line 14, in f
result = lst[10]
IndexError: list index out of range
In order to handle exceptions -like IndexError
in our example, we usually use
try, except, else, finally
.
import logging
logging.basicConfig(
level=logging.INFO,
format="[%(asctime)s] [%(levelname)-7s] : %(message)s",
datefmt="%Y-%m-%d %H:%M:%S %z",
)
logger = logging.getLogger(__name__)
def g(lst):
"""Dummy function to show try/except"""
try:
result = lst[10]
except IndexError:
result = 0
logger.warning("<lst> doesn't have 10 elements")
else:
logger.info("<lst> does have 10 elements")
finally:
logger.info("I always run")
logger.info(f"{result = }")
return result
if __name__ == "__main__":
g(lst=list(range(10)))
Now if you run the code, you will get:
[2022-08-13 17:54:12 +0300] [WARNING] : <lst> doesn't have 10 elements
[2022-08-13 17:54:12 +0300] [INFO ] : I always run
[2022-08-13 17:54:12 +0300] [INFO ] : result = 0
This is how we handle errors in Python in a basic way.
In order to suppress IndexError
you just simply pass
the except
block:
def x(lst, initial_value=0):
"""Dummy function to show basic suppress"""
try:
initial_value += lst[10]
except IndexError:
pass
return initial_value
if __name__ == "__main__":
logger.info(x(lst=list(range(10))))
Note
Never use Exception
or BaseException
for wildcard exception catching. You
should always use specific exception that you expect to be raised.
# Don't use wildcard Exception catching
try:
result = lst[10]
except Exception:
result = 0
contextlib.suppress
I’d like to introduce that there is also another way to deal with exceptions
;
with a contextmanager
named suppress
.
|
|
This suppress
is equivalent to:
try:
result = list[10]
except IndexError:
pass
Note
You can get more information from official documentation contextlib.suppress.
You may think where should or can I use suppress
. To give you an instance
pytest
uses raises
in a similar way:
|
|
You may also just simply suppress an error rather than constructing a control flow logic.
Undoubtedly using contextlib.suppress
depends on business logic, code
readability and maintainability. However I believe that it’s always good to know
there are another alternatives to approach a problem.
All done!