Quick Python Tip: Suppress Known Exception Without Try Except | by Christopher Tao | Towards Data Science

It is very common to use thetry ... except ... block to handle exceptions in Python. It enabled us to apply some special operations when there is something goes wrong.
However, there is a special case that
We know that this exception may happen
We don’t care about this exception
If it happened, just ignore it without doing anything
If the situation satisfies the above conditions, you don’t have to use try ... except ... to handle the exceptions. Instead, the Python built-in library contextlib provides a function called suppress to handle this more elegantly.
Suppose we have a list of numbers that may contain zeros in them. We want to get the reciprocal number of every number in this list and then have the sum of them. If there are zeros, just ignore them.
Firstly, let’s use the random library to generate such a list.
import randomnums = [random.randint(-3, 3) for i in range(20)]
The above code generates a list of integers between (-3, 3) with a size of 20. Please note that you can have a list without any zeros. If this happened, just generate another one. We will need some zeros in this experiment.
Now, suppose we want to get reciprocal numbers of all the numbers in this list. Note that the number zero has no reciprocal. So, if we write code as follows without handling exceptions, a ZeroDivisionError will be thrown.
results = [1/num for num in nums]
The most common and intuitive way of solving this problem is to have a try ... except ... block to catch the ZeroDivisionError exception and ignore it.
result = 0for num in nums:    try:        result += 1/num    except ZeroDivisionError:        passresult
In the above code, we catch the ZeroDivisionError exception and use pass to ignore it. So, when this exception happens, nothing will be thrown and the program will just keep running by ignoring the zero number.
Now, I’m going to introduce another approach to you, which makes your code more elegant.
Before using this approach, we need to import it from contextlib first.
from contextlib import suppress
The suppress function needs to be used with the with statement as follows:
result = 0for num in nums:    with suppress(ZeroDivisionError):        result += 1/numresult
Isn’t that more concise and intuitive? It is more “Pythonic” too, in my opinion.
So, with the suppress function, the exception that passed in as a parameter will be ignored.
This section is updated based on a question from @Felix’s response.
The short answer is: No, you don’t have to use it.
In the question, I was asked why not fix it as follows:
result = sum([1/x for x in nums if x != 0])
That is absolutely right. In this article, I just wanted to create such a scenario that I can demonstrate suppress. My example isn’t perfect, because it is indeed more preferable to be fixed by the above solution rather than using suppress function. But I think the value of the suppress function exists in other scenarios. For example, what if the list is like this:
nums = [3, -1, -2, 1, 1, 0, 3, 1, -2, 1, 0, -1, -1, -1, 3, -2, -1, 3, '3', -1] 
Please note that there is a string ‘3’ at the second last position. Now, we have two possible exceptions. You could also handle it in the above way:
result = sum([1/x for x in nums if x != 0 and type(x) == int]) 
Or, with the suppress function, you just add another exception type:
for num in nums:    with suppress(ZeroDivisionError, TypeError):        result += 1/num
Then, what if there are more possible exceptions? Rather than adding more and more conditions in the list comprehension, I believe using suppress is more elegant.
Additionally, what if you have more than 2 possible exceptions? Or, let’s say you don’t care what is the exception, just want to bypass it whenever it happens.
for num in nums:    with suppress(Exception):        result += 1/num
So, you suppressed any types of exceptions :)
However, there is a limitation of suppress function. That is, you can’t put your for-loop inside the suppress with statement as follows.
result = 0with suppress(ZeroDivisionError):    for num in nums:        result += 1/numresult
Why do we have a different result here? That is because the for-loop will be break once the exception happened. Although the exception was still ignored, all the numbers after the 0 will be ignored too.
In this article, I have shared an alternative approach to the try ... except ... when you simply want to catch the exception and ignore it, which is the suppress function from contextlib that is a built-in library in Python. It is more elegant in terms of the coding style I believe.
However, I also want to put some thoughts of mine regarding this
It has a limitation that we couldn’t put iterating such as for-loops in it
We will need to import the function before use, so maybe use this when we want to use it in multiple spots in our code
Every day we can learn something. Happy coding!
medium.com
If you feel my articles are helpful, please consider joining Medium Membership to support me and thousands of other writers! (Click the link above)