How to properly ignore exceptions
Asked Answered
W

12

950

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
Wendell answered 8/4, 2009 at 16:23 Comment(4)
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.Dexterous
Important read when thinking about ignoring exceptions: Why is “except: pass” a bad programming practice?Iyar
Imagine doing this in real life. try: get_cash('$1000') except: pass # meh, it will probably be fineBriannebriano
Not work for me: I made a checksum function that generates expected overflows: try: a1[3]=a1[0]+a1[1]+a1[2] except: pass That generates error at the output window: d:\jlope\Phyton\Prue\prue12_ftdi:33: RuntimeWarning: overflow encountered in ushort_scalarsLimulus
F
1219
try:
    doSomething()
except Exception: 
    pass

or

try:
    doSomething()
except: 
    pass

The difference is that the second one will also catch KeyboardInterrupt, SystemExit and stuff like that, which are derived directly from BaseException, not Exception.

See documentation for details:

However, it is generally bad practice to catch every error - see Why is "except: pass" a bad programming practice?

Farfamed answered 8/4, 2009 at 16:25 Comment(6)
Note that StopIteration and Warning both inherit from Exception as well. Depending on your needs, you may want to inherit from StandardError instead.Gracioso
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).Dermatology
-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:Lubric
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)Alphonse
Jabbas answer should be accepted as for versions later than Python 3.4: https://mcmap.net/q/53329/-how-to-properly-ignore-exceptionsJersey
realpython.com/the-most-diabolical-python-antipatternEbby
L
165

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("/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?

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

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

import errno

try:
    shutil.rmtree(path)
except OSError as e:
    if e.errno != errno.ENOENT:
        # ignore "No such file or directory", but re-raise other errors
        raise
Lubric answered 9/4, 2009 at 21:48 Comment(2)
shutil.rmtree is not the best example, because you would just use ignore_errors=True for that function..Grenadine
Really like this answer, but you did not explain how you went from Errno 2 to errno.ENOENT.. Could be helpful for a lot of people. ;) See Python Standard Errno System Symbols for more info.Nab
A
122

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
Adoration answered 7/9, 2013 at 20:55 Comment(1)
That is nice. Even better to do it that way \n sp=suppress(Exception)\n with sp:\n # your codeTarr
D
118

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
Dermatology answered 8/4, 2009 at 16:32 Comment(0)
A
60

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")

Also note that you can capture the exception like this:

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

...and re-raise the exception like this:

>>> try:
...     raise NameError('HiThere')
... except NameError:
...     print('An exception flew by!')
...     raise

Also, multiple exception types can be handled as a parenthesized tuple:

try:
    i_might_fail()
except (ValueError, TypeError) as ex:
    print('I failed with: ', ex)

...or as separate except clauses:

try:
    i_might_fail()
except ValueError:
    print('handling a ValueError...')
except TypeError:
    print('handling a TypeError...')

...see the python tutorial.

Ambulacrum answered 5/3, 2010 at 23:2 Comment(0)
D
46

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 
Dexterous answered 22/1, 2015 at 4:42 Comment(0)
E
14

I needed to ignore errors in multiple commands and fuckit did the trick

import fuckit

@fuckit
def helper():
    print('before')
    1/0
    print('after1')
    1/0
    print('after2')

helper()
Engram answered 1/12, 2018 at 21:23 Comment(1)
+1 because You definitely made my day because inside this source code you can learn some extremely useful things like modifying the live stackAladdin
C
11
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.

Choice answered 19/11, 2009 at 22:35 Comment(1)
Finally a good explanation of else in this context. And to add that finally will always run after any (or no exception).Howlan
B
11

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 the exception is:( i.e. try catch without handling the exception and print the exception.)

import sys
try:
    doSomething()
except:
    print "Unexpected error:", sys.exc_info()[0]
Bluebottle answered 12/10, 2011 at 5:36 Comment(0)
F
5

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...
Floeter answered 18/11, 2010 at 10:27 Comment(0)
S
1

Well, this is not a try-except but still another way to handle exceptions if object-oriented programming is your thing:

class MyExceptionHandler:

    def __enter__(self):
        ... # Do whatever when "with" block is started
        return self

    def __exit__(self, exc_type, exc_value, tb):
        return True

And then to the actual code:

with MyExceptionHandler():
     ... # Code that may or may not raise an exception
     shutil.rmtree(path)

How this works?

  • __enter__ is run when entering the with block.
  • __exit__ is run when exiting the with block
    • This should return True to silence the possible exception.
    • This should return None (or something which is considered False) to not silence the potential exception.
    • The exception type, actual exception and its traceback are passed as (positional) arguments. You can use these to determine what to do.

As a final note, prefer try-except. This may be useful if you need more abstraction than usual.

Sonometer answered 28/10, 2021 at 6:44 Comment(1)
Elegant but not obvious, but actually coolCharades
B
-5

I usually just do:

try:
    doSomething()
except:
    _ = ""
Bibliotherapy answered 26/1, 2020 at 15:25 Comment(2)
I'd suggest that you replace _ = "" with pass.Arquit
And if you are using this fragment in code that has the variable _ assigned before this block, if an exception occurs, then after this block the variable will have changed value.Clear

© 2022 - 2024 — McMap. All rights reserved.