How to properly ignore Exceptions?
There are several ways of doing this.
However, the choice of example has a simple solution that does not cover the general case.
Specific to the example:
Instead of
try:
shutil.rmtree(path)
except:
pass
Do this:
shutil.rmtree(path, ignore_errors=True)
This is an argument specific to shutil.rmtree
. You can see the help on it by doing the following, and you’ll see it can also allow for functionality on errors as well.
>>> import shutil
>>> help(shutil.rmtree)
Since this only covers the narrow case of the example, I’ll further demonstrate how to handle this if those keyword arguments didn’t exist.
General approach
Since the above only covers the narrow case of the example, I’ll further demonstrate how to handle this if those keyword arguments didn’t exist.
New in Python 3.4:
You can import the suppress
context manager:
from contextlib import suppress
But only suppress the most specific exception:
with suppress(FileNotFoundError):
shutil.rmtree(path)
You will silently ignore a FileNotFoundError
:
>>> with suppress(FileNotFoundError):
... shutil.rmtree('bajkjbkdlsjfljsf')
...
>>>
From the docs:
As with any other mechanism that completely suppresses exceptions,
this context manager should be used only to cover very specific errors
where silently continuing with program execution is known to be the
right thing to do.
Note that suppress
and FileNotFoundError
are only available in Python 3.
If you want your code to work in Python 2 as well, see the next section:
Python 2 & 3:
When you just want to do a try/except without handling the exception,
how do you do it in Python?Is the following the right way to do it?
try : shutil.rmtree ( path ) except : pass
For Python 2 compatible code, pass
is the correct way to have a statement that’s a no-op. But when you do a bare except:
, that’s the same as doing except BaseException:
which includes GeneratorExit
, KeyboardInterrupt
, and SystemExit
, and in general, you don’t want to catch those things.
In fact, you should be as specific in naming the exception as you can.
Here’s part of the Python (2) exception hierarchy, and as you can see, if you catch more general Exceptions, you can hide problems you did not expect:
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StandardError
| +-- BufferError
| +-- ArithmeticError
| | +-- FloatingPointError
| | +-- OverflowError
| | +-- ZeroDivisionError
| +-- AssertionError
| +-- AttributeError
| +-- EnvironmentError
| | +-- IOError
| | +-- OSError
| | +-- WindowsError (Windows)
| | +-- VMSError (VMS)
| +-- EOFError
... and so on
You probably want to catch an OSError here, and maybe the exception you don’t care about is if there is no directory.
We can get that specific error number from the errno
library, and reraise if we don’t have that:
import errno
try:
shutil.rmtree(path)
except OSError as error:
if error.errno == errno.ENOENT: # no such file or directory
pass
else: # we had an OSError we didn't expect, so reraise it
raise
Note, a bare raise raises the original exception, which is probably what you want in this case. Written more concisely, as we don’t really need to explicitly pass
with code in the exception handling:
try:
shutil.rmtree(path)
except OSError as error:
if error.errno != errno.ENOENT: # no such file or directory
raise
- Use the
pass
Statement in theexcept
Block in Python - Use the
sys.exc_clear()
Statement in theexcept
Block in Python
An exception is an event that, when raised, alters the flow of the program.
Exceptions result from the program being syntactically correct but still giving an error on the execution of the code. This error does not halter the program’s execution but rather changes the default flow of the program.
In Python, we handle exceptions using the try...except
block. This tutorial will discuss several methods to ignore an exception and proceed with the code in Python.
Use the pass
Statement in the except
Block in Python
The pass
statement can be considered as a placeholder in Python programming. It returns a NULL
statement and, therefore, produces no value. However, the Python interpreter does not ignore the pass statement, and we prevent getting errors for empty code where the statement is used.
When the pass
statement is used in the try...except
statements, it simply passes any errors and does not alter the flow of the Python program.
The following code uses the pass
statement in the except
block to ignore an exception and proceed with the code in Python.
try:
print(hey)
except Exception:
pass
print("ignored the exception")
The above code provides the following output.
Although this function always works in Python 3 and above, using the pass
statement is considered a bad programming practice. It doesn’t provide a solution to the errors that might arise during the program. Moreover, identifying the errors in a given program is much more difficult as it ignores every single error.
Use the sys.exc_clear()
Statement in the except
Block in Python
In Python 2, the last thrown exception gets remembered by the interpreter, while it does not happen in the newer versions of Python. Therefore, the sys.exc_clear()
statement is not needed in the versions released after Python 3. The sys.exc_clear()
statement can be utilized to clear the last thrown exception of the Python interpreter.
The following code uses the sys.exc_clear()
statement in the except
block to ignore an exception and proceed with the code in Python.
try:
print(hey)
except Exception:
sys.exc_clear()
print("ignored the exception")
Although these two ways manage to make the program run without any errors, it is not recommended to ignore all the errors in a program. However, ignoring only a particular error or some errors is a practice that most programmers do for a healthy program.
Limiting the use of the pass
statement and sys.exc_clear()
statement in a program also improves the readability and identification of errors of a program.
If you are an application developer, you might have to implement an error-free code that is well tested. In my instances, we would like to ignore I/O or Numerical exceptions. In this blog post, you will learn how we can safely ignore exceptions in Python.
How to Properly Ignore Exceptions in Python?
Imagine you are working on an application where you have a list of numbers and would like to output the reciprocal of the numbers. If by mistake the list consists of 0, then the program would crash since we are diving 1 by 0 which will raise an exception. We can implement this in a bug free manner by using a try and except block.
We can achieve this by the following two steps
- Put the logic of taking the reciprocal of the number in try block
- Implement an exception block that is executed wherever the number is 0. Continue with the rest of the logic
Without a try-except Block
Let us first implement the logic using a simple for loop. As you can see in the output below, the program crashed when the number was 0
numbers = [12, 1, 0, 45, 56] for number in numbers: print('result is {}'.format(1/number))
Output
result is 0.08333333333333333 result is 1.0 --------------------------------------------------------------------------- ZeroDivisionError Traceback (most recent call last) <ipython-input-27-c1f2d047aa92> in <module>() 1 for number in numbers: ----> 2 print('result is {}'.format(1/number)) ZeroDivisionError: division by zero
With a try-except Block
Let us now see how we can safely ignore an exception
numbers = [12,1,0,45,56] for number in numbers: try: print('result is {}'.format(1/number)) except Exception as e: print('Ignoring Exception', e)
Output
result is 0.08333333333333333 result is 1.0 Ignoring Exception division by zero result is 0.022222222222222223 result is 0.017857142857142856
Summary
In this blog post you learned how to safely ignore exceptions in Python. You learnt how to use a try and except block and continue with the program if an exception is encountered.