How to properly ignore exceptions

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP

How to properly ignore exceptions



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





Weird that nobody mentioned it until now (I did in my answer), but for this specific function, you can just do shutil.rmtree(path, ignore_errors=True). This won't apply for most functions, however.
– Aaron Hall
Apr 19 '17 at 14:48


shutil.rmtree(path, ignore_errors=True)





Important read when thinking about ignoring exceptions: Why is “except: pass” a bad programming practice?
– poke
Sep 25 '17 at 9:55




11 Answers
11


try:
doSomething()
except:
pass



or


try:
doSomething()
except Exception:
pass



The difference is, that the first one will also catch KeyboardInterrupt, SystemExit and stuff like that, which are derived directly from exceptions.BaseException, not exceptions.Exception.
See documentation for details:


KeyboardInterrupt


SystemExit


exceptions.BaseException


exceptions.Exception





Note that StopIteration and Warning both inherit from Exception as well. Depending on your needs, you may want to inherit from StandardError instead.
– Ben Blank
Apr 8 '09 at 17:01





@Ben: both of these are "normal" exceptions, so no problem there..
– vartec
Apr 8 '09 at 17:03





This is true, but if you're not careful, you can run into subtle bugs (especially if you're doing something other than passing on StopIteration).
– Jason Baker
Apr 8 '09 at 17:46





-1, try: shuti.rmtree(...) except: pass will crudely suppress any errors (even if you misspell shutil resulting in a NameError) - at the very least do except OSError:
– dbr
Jul 23 '12 at 13:59


try: shuti.rmtree(...) except: pass


shutil


NameError


except OSError:





This answer, while informative, is missing a crucial information - you should never catch an exception this way. Instead, you should always try to catch just the exceptions you care about, otherwise you will have nightmares when hunting down trivial bugs, hidden by your generic "except"s. See dbr's answer for more info. (I know this was not the original question - but anyone looking for this will just take your snippet and use it as is)
– johndodo
Jan 20 '16 at 10:30




It's generally considered best-practice to only catch the errors you are interested in. In the case of shutil.rmtree it's probably OSError:


shutil.rmtree


OSError


>>> shutil.rmtree("/fake/dir")
Traceback (most recent call last):
[...]
OSError: [Errno 2] No such file or directory: '/fake/dir'



If you want to silently ignore that error, you would do:


try:
shutil.rmtree(path)
except OSError:
pass



Why? Say you (somehow) accidently pass the function an integer instead of a string, like:


shutil.rmtree(2)



It will give the error "TypeError: coercing to Unicode: need string or buffer, int found" - you probably don't want to ignore that, which can be difficult to debug.



If you definitely want to ignore all errors, catch Exception rather than a bare except: statement. Again, why?


Exception


except:



Not specifying an exception catches every exception, including the SystemExit exception which for example sys.exit() uses:


SystemExit


sys.exit()


>>> try:
... sys.exit(1)
... except:
... pass
...
>>>



Compare this to the following, which correctly exits:


>>> try:
... sys.exit(1)
... except Exception:
... pass
...
shell:~$



If you want to write ever better behaving code, the OSError exception can represent various errors, but in the example above we only want to ignore Errno 2, so we could be even more specific:


OSError


Errno 2


try:
shutil.rmtree(path)
except OSError, e:
if e.errno == 2:
# suppress "No such file or directory" error
pass
else:
# reraise the exception, as it's an unexpected error
raise



You could also import errno and change the if to if e.errno == errno.ENOENT:


import errno


if


if e.errno == errno.ENOENT:



When you just want to do a try catch without handling the exception, how do you do it in Python?



It depends on what you mean by "handling."



If you mean to catch it without taking any action, the code you posted will work.



If you mean that you want to take action on an exception without stopping the exception from going up the stack, then you want something like this:


try:
do_something()
except:
handle_exception()
raise #re-raise the exact same exception that was thrown



First I quote the answer of Jack o'Connor from this thread. The referenced thread got closed so I write here:



"There's a new way to do this coming in Python 3.4:


from contextlib import suppress

with suppress(Exception):
# your code



Here's the commit that added it: http://hg.python.org/cpython/rev/406b47c64480



And here's the author, Raymond Hettinger, talking about this and all sorts of other Python hotness: https://youtu.be/OSGv2VnC0go?t=43m23s



My addition to this is the Python 2.7 equivalent:


from contextlib import contextmanager

@contextmanager
def ignored(*exceptions):
try:
yield
except exceptions:
pass



Then you use it like in Python 3.4:


with ignored(Exception):
# your code



For completeness:


>>> def divide(x, y):
... try:
... result = x / y
... except ZeroDivisionError:
... print "division by zero!"
... else:
... print "result is", result
... finally:
... print "executing finally clause"



...from the python tutorial.



Also note that you can capture the exception like this:


>>> try:
... this_fails()
... except ZeroDivisionError as detail:
... print 'Handling run-time error:', detail



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.



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.


shutil.rmtree


>>> 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.



You can import the suppress context manager:


suppress


from contextlib import suppress



But only suppress the most specific exception:


with suppress(FileNotFoundError):
shutil.rmtree(path)



You will silently ignore a FileNotFoundError:


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.


suppress


FileNotFoundError



If you want your code to work in Python 2 as well, see the next section:



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.


pass


except:


except BaseException:


GeneratorExit


KeyboardInterrupt


SystemExit



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:


errno


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:


pass


try:
shutil.rmtree(path)
except OSError as error:
if error.errno != errno.ENOENT: # no such file or directory
raise



@When you just want to do a try catch without handling the exception, how do you do it in Python?



This will help you to print what exception is:( i.e. try catch without handling the exception and print the exception.)



reg,
Tilokchan


try:
doSomething()
except Exception:
pass
else:
stuffDoneIf()
TryClauseSucceeds()



FYI the else clause can go after all exceptions and will only be run if the code in the try doesn't cause an exception.



In Python, we handle exceptions similar to other language, but the difference is some syntax difference, for example,


try:
#Your code in which exception can occur
except <here we can put in a particular exception name>:
# We can call that exception here also, like ZeroDivisionError()
# now your code
# We can put in a finally block also
finally:
# Your code...



Simply raise the relevant exception, just like this:


try:
raise NameError('Joan')
except NameError:
print 'An exception just raised again by Joan!'
raise



As simple as that. :)



For more details, do read this documentation:
https://docs.python.org/3.6/tutorial/errors.html



Handling an exception in Python: If you have some suspicious code that may raise an exception, you can defend your program by placing the suspicious code in a try: block.


try:
# Your statements .............
except ExceptionI:
# Your statements.............
except ExceptionII:
# Your statements..............
else:
# Your statements






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Comments

Popular posts from this blog

Executable numpy error

PySpark count values by condition

Trying to Print Gridster Items to PDF without overlapping contents