How can I write a `try`/`except` block that catches all exceptions?
Asked Answered
C

10

1151

How can I write a try/except block that catches all exceptions?

Cryoscopy answered 14/2, 2011 at 9:46 Comment(6)
To be more precise, catching all possible exceptions is only a problem if they are caught silently. It's hard to think of where else this approach is appropriate, other than where the caught error messages are printed to sys.stderr and possibly logged. That is a perfectly valid and common exception.Outskirts
did you try: try: whatever() except Exception as e: exp_capture() ?Ensiform
Related: Why is except: pass a bad programming practice?Katy
See also Bad idea to catch all exceptions in PythonKaty
related: #4565059Ensiform
fyi, finally blocks always get excuted no matter what afaik.Ensiform
A
761

You can but you probably shouldn't:

try:
    do_something()
except:
    print("Caught it!")

However, this will also catch exceptions like KeyboardInterrupt and you usually don't want that, do you? Unless you re-raise the exception right away - see the following example from the docs:

try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except IOError as (errno, strerror):
    print("I/O error({0}): {1}".format(errno, strerror))
except ValueError:
    print("Could not convert data to an integer.")
except:
    print("Unexpected error:", sys.exc_info()[0])
    raise
Abigael answered 14/2, 2011 at 9:49 Comment(14)
Possible workaround: effbot.org/zone/stupid-exceptions-keyboardinterrupt.htmAlameda
You really should print to stderr.Bartel
I very very strongly disagree with the statement, "shouldn't." You should do it sparingly. There are times when you're dealing with third party libraries (sometimes dynamically loaded!!) that have gone totally crazy with exceptions and tracking them all down can be a very painful task, and if you miss just one, you have a very very huge painful bug in your system. That being said, it's good to track down as many as you can and handle them appropriately and then have a backup catch all for the ones you miss.Malayan
What I find also weird is that in a duck typing language where you don't declare instance variables, it's suddenly very concerned about not typing all of your exceptions. Hmm!Malayan
Still missing the except Exception:.Hispanicize
@PedroGordo - I am pretty sure the final except is doing the same thing as except Exception: and is referencing the exception with sys.exc_info()[0]. I am not a Python guy, so someone will need to confirm this.Oxalis
@Oxalis if memory serves me right, you needed to explicitly declare that, but like you, I'm not a Python expert, so I defer the certainty to someone with more experience. :)Hispanicize
can we get a confirmation of the difference of except Exception as e: vs sys.exc_info()[0]?Ensiform
why don't you want to capture keyboard interrupts?Ensiform
is there something wrong with except Exception as e: why didn't you suggest that? It seems better than just except: at leat that one you can get e and print it or something...no?Ensiform
To add to @Malayan - you should probably catch only exceptions that are important and you know of and, in case your app must NOT fail in that moment - have a default exception catcher - that way - your app never fails at that point by exception, but, for the known you can provide a better message for example :)Leclair
Doesn't work with Python 3. Follow the new syntax here: #7775562Salomo
except: is basically short for except BaseException:. The exceptions that inherit from BaseException directly, rather than from Exception, are the ones you virtually never want to catch without re-raising.Coherent
fyi, finally blocks always get excuted no matter what afaik.Ensiform
E
1340

Apart from a bare except: clause (which as others have said you shouldn't use), you can simply catch Exception:

import traceback
import logging

try:
    whatever()
except Exception as e:
    logging.error(traceback.format_exc())
    # Logs the error appropriately. 

You would normally only ever consider doing this at the outermost level of your code if for example you wanted to handle any otherwise uncaught exceptions before terminating.

The advantage of except Exception over the bare except is that there are a few exceptions that it wont catch, most obviously KeyboardInterrupt and SystemExit: if you caught and swallowed those then you could make it hard for anyone to exit your script.

Eclogite answered 14/2, 2011 at 12:26 Comment(15)
I had the same thing in my mind, but their is a disadvantage , suppose their are two error when once is caught and and in except you are just printing you will get out of the try block and you will never know the second error...Lately
For anyone wondering, totally contrary to my expectation this will still catch non-exception subclassing things like ints, at least in python 2.x.Wyman
@JosephGarvin, that's incorrect, i.e. this will not catch "non-exceptions" that don't subclass Exception. Note that it's impossible to raise an int as an exception, and attempting to do so raises a TypeError exception, which is what would be caught by the enclosing except Exception clause in such a case. On the other hand, an old-style class can be raised and qualifies as a "non-exception" that doesn't subclass Exception - this will be caught by a bare except clause but not by an except Exception clause.Cavatina
@JosephGarvin check this blog entry: chris-lamb.co.uk/posts/no-one-expects-string-literal-exception I'm with @Cavatina on this one, your testing just masked the TypeErrorEclogite
what is the difference of the above with doing: sys.exc_info()[0] ?Ensiform
sorry for the noob question, but what is wrong with catching KeyboardInterrupt interrupts or SystemExit ? What would happen?Ensiform
@CharlieParker nothing wrong with catching them if that's what you want but you mostly don't. Calling sys.exit() usually means you expect the app to terminate but if you catch SystemExit it won't. Likewise if you hit control-C on a running script (Ctrl-break on windows) you expect the program to stop, not to catch the error and keep going. But you can catch either/both of these if you want to do cleanup before existing.Eclogite
An example: Let's say a user uses some piece of code in a jupyter Notebook, looping over multiple elements of something, puts a try/except clause inside the loop, and only has some logging and a continue under the except ("I want the function to work on the elements it can, and not stop just because some element is bad"). If the except is a bare except, the notebook can't be stopped with a KeyboardInterrupt (which is very common)... an except Exception (or except StandardError) would be better even without knowing/caring about the source of the error.Cabalistic
I have my jobs running from a HPC manager. I want to capture when the (slurm, qsub, condor) manager does an exit (to email myself about it with my custom email). Will except: catch that? But it doesn't give me a handle for e though :(Ensiform
@CharlieParker you could try except BaseException as e: notify_user(e); raise that would catch all exceptions and do whatever notification you need, but I don't know HPC so you might want to ask as a new SO question.Eclogite
I thought this caught EVERY exception, and it took me a while to figure out why I couldn't catch KeyboardInterrupt ....Iso
This 'you shouldn't do that' refrain is only valid when using native python code with native python dependencies. Once you are interfacing with compiled languages (most of python3's versatile dependencies do so), you will require catch-alls to ensure memory safety. This is because python3 is reluctant to call the del method under some conditions.Creosote
fyi, finally blocks always get excuted no matter what afaik.Ensiform
Why the as e in the code? Just an unused variable, or am I missing something?Fanaticize
@Fanaticize in this case e is an unused variable but can often be usefulEclogite
A
761

You can but you probably shouldn't:

try:
    do_something()
except:
    print("Caught it!")

However, this will also catch exceptions like KeyboardInterrupt and you usually don't want that, do you? Unless you re-raise the exception right away - see the following example from the docs:

try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except IOError as (errno, strerror):
    print("I/O error({0}): {1}".format(errno, strerror))
except ValueError:
    print("Could not convert data to an integer.")
except:
    print("Unexpected error:", sys.exc_info()[0])
    raise
Abigael answered 14/2, 2011 at 9:49 Comment(14)
Possible workaround: effbot.org/zone/stupid-exceptions-keyboardinterrupt.htmAlameda
You really should print to stderr.Bartel
I very very strongly disagree with the statement, "shouldn't." You should do it sparingly. There are times when you're dealing with third party libraries (sometimes dynamically loaded!!) that have gone totally crazy with exceptions and tracking them all down can be a very painful task, and if you miss just one, you have a very very huge painful bug in your system. That being said, it's good to track down as many as you can and handle them appropriately and then have a backup catch all for the ones you miss.Malayan
What I find also weird is that in a duck typing language where you don't declare instance variables, it's suddenly very concerned about not typing all of your exceptions. Hmm!Malayan
Still missing the except Exception:.Hispanicize
@PedroGordo - I am pretty sure the final except is doing the same thing as except Exception: and is referencing the exception with sys.exc_info()[0]. I am not a Python guy, so someone will need to confirm this.Oxalis
@Oxalis if memory serves me right, you needed to explicitly declare that, but like you, I'm not a Python expert, so I defer the certainty to someone with more experience. :)Hispanicize
can we get a confirmation of the difference of except Exception as e: vs sys.exc_info()[0]?Ensiform
why don't you want to capture keyboard interrupts?Ensiform
is there something wrong with except Exception as e: why didn't you suggest that? It seems better than just except: at leat that one you can get e and print it or something...no?Ensiform
To add to @Malayan - you should probably catch only exceptions that are important and you know of and, in case your app must NOT fail in that moment - have a default exception catcher - that way - your app never fails at that point by exception, but, for the known you can provide a better message for example :)Leclair
Doesn't work with Python 3. Follow the new syntax here: #7775562Salomo
except: is basically short for except BaseException:. The exceptions that inherit from BaseException directly, rather than from Exception, are the ones you virtually never want to catch without re-raising.Coherent
fyi, finally blocks always get excuted no matter what afaik.Ensiform
V
185

To catch all possible exceptions, catch BaseException. It's on top of the Exception class hierarchy:

Python 3: https://docs.python.org/3.12/library/exceptions.html#exception-hierarchy

Python 2.7: https://docs.python.org/2.7/library/exceptions.html#exception-hierarchy

try:
    something()
except BaseException as error:
    print('An exception occurred: {}'.format(error))

But as other people mentioned, you would usually not need this, only for very specific cases.

Venusian answered 24/7, 2015 at 11:39 Comment(6)
Is wishing to save progress of a long-running job after pressing Ctrl-C that unusual?Mayle
I have my jobs running from a HPC manager. I want to capture when the (slurm, qsub, condor) manager does an exit (to email myself about it with my custom email). Will except: catch that? But it doesn't give me a handle for e though :(Ensiform
In Python, all exceptions must be instances of a class that derives from BaseException, but if you can omit it for a general case - omit it, problem is, linters wine about it.Leclair
@Mayle That's what signal handlers are for. It's the default signal handler for SIGINT that raises KeyboardInterrupt in the first place. Sure, you can catch KeyboardInterrupt, but it's just one of many signals that could terminated your program prematurely. Those don't generate any kind of exception, so you may as well handle them all uniformly.Coherent
CAUTION: using BaseException like this is rarely what you want. Do you seriously want to catch keyboard interupts and sys.exit? Probably NOT! All user-defined exceptions should inherit from Exception. take a look at the exception class heirarchy. dotnettutorials.net/wp-content/uploads/2020/07/…Stretch
This worked perfectly fine for me, it catches all the errors you could have implemented elsewhere when using like a global class. It's not the perfect solution for local implementation but for a production mode system it's niceCtn
B
120

You can do this to handle general exceptions

try:
    a = 2/0
except Exception as e:
    print e.__doc__
    print e.message
Beason answered 14/7, 2013 at 19:27 Comment(8)
This may not catch all exceptions, as the base class for all exceptions is BaseException and I have encountered production code that is not in the Exception class family. See docs.python.org/3/library/… for details about this.Salpingotomy
This does not catch all exceptions.Elba
Technically, it should catch all non-system-exiting exceptions. From the docs @Salpingotomy linked: "exception BaseException: The base class for all built-in exceptions. It is not meant to be directly inherited by user-defined classes (for that, use Exception)." Unless you're working with code that ignores this, or you need to catch system-exiting exceptions, the above should be ok to use.Devitt
@PeterCassetta when would one want to catch system exiting exceptions? It seems the common thread in the question that we don't want to catch these, but I don't understand why. Why not usually?Ensiform
not all exceptions will have a message attribute.Expansile
my IDE tells me there's a syntax error end of statement expected after print, idk why - maybe something to do with python3 vs python2?Shack
Because in Python 3 print is a function and not a statement. Thus you need to call it with (). e.g print(e.message)Beason
@Charlie Parker (1) KeyboardInterrupt triggered by Ctrl+C can happen at any point; it's sometimes desired to handle it in a specific place but it'd be silly to swallow it by random try..BODY..except..HANDLE intended for handling errors from BODY. (2) SystemExit raised by sys.exit() is similar. (3) GeneratorExit is not "system-exiting", but it is "injected" by generator.close() with intent to terminate it, in that sense it's a local analogue to KeyboardInterrupt.Saloon
J
65

Very simple example, similar to the one found here:

http://docs.python.org/tutorial/errors.html#defining-clean-up-actions

If you're attempting to catch ALL exceptions, then put all your code within the "try:" statement, in place of 'print "Performing an action which may throw an exception."'.

try:
    print "Performing an action which may throw an exception."
except Exception, error:
    print "An exception was thrown!"
    print str(error)
else:
    print "Everything looks great!"
finally:
    print "Finally is called directly after executing the try statement whether an exception is thrown or not."

In the above example, you'd see output in this order:

1) Performing an action which may throw an exception.

2) Finally is called directly after executing the try statement whether an exception is thrown or not.

3) "An exception was thrown!" or "Everything looks great!" depending on whether an exception was thrown.

Hope this helps!

Justificatory answered 14/2, 2011 at 16:21 Comment(3)
I have my jobs running from a HPC manager. I want to capture when the (slurm, qsub, condor) manager does an exit (to email myself about it with my custom email). Will except: catch that? But it doesn't give me a handle for e though :(Ensiform
except Exception, error:^SyntaxError: invalid syntaxCannibalism
@Cannibalism try: except Exception as error: -- If you're running Python3.Justificatory
M
43

There are multiple ways to do this in particular with Python 3.0 and above

Approach 1

This is simple approach but not recommended because you would not know exactly which line of code is actually throwing the exception:

def bad_method():
    try:
        sqrt = 0**-1
    except Exception as e:
        print(e)

bad_method()

Approach 2

This approach is recommended because it provides more detail about each exception. It includes:

  • Line number for your code
  • File name
  • The actual error in more verbose way

The only drawback is tracback needs to be imported.

import traceback

def bad_method():
    try:
        sqrt = 0**-1
    except Exception:
        print(traceback.print_exc())

bad_method()
Mordy answered 28/1, 2019 at 5:46 Comment(2)
I have my jobs running from a HPC manager. I want to capture when the (slurm, qsub, condor) manager does an exit (to email myself about it with my custom email). Will except: catch that? But it doesn't give me a handle for e though :(Ensiform
Is it possible to concatenate to traceback.print_exc()?Pointing
P
26

I've just found out this little trick for testing if exception names in Python 2.7 . Sometimes i have handled specific exceptions in the code, so i needed a test to see if that name is within a list of handled exceptions.

try:
    raise IndexError #as test error
except Exception as e:
    excepName = type(e).__name__ # returns the name of the exception
Papist answered 28/11, 2016 at 11:16 Comment(2)
I have my jobs running from a HPC manager. I want to capture when the (slurm, qsub, condor) manager does an exit (to email myself about it with my custom email). Will except: catch that? But it doesn't give me a handle for e though :(Ensiform
To be quite honest, I am not familiar with HPC... If it is integrated with/for python it should have corresponding exceptions implemented. If not you can try 3rd part library that has it (dunno which) or making a task listener that would search for flag set by HPC. If all that fails you can try and code some yourself, 'exception' class is inheritable and dive into processes/drivers. Other than that, due to lack of more information and No Opinions policy of SO, I would suggest asking a new question witch HPC in title and tags - if not asked before. Cheer :)Papist
G
24

I am adding the bonus method that can catch the exception with full traceback which can help you to understand the error more.

Python 3

import traceback

try:
    # your code goes here
except Exception as e:
    print(e)
    traceback.print_exc()
Germane answered 9/12, 2021 at 10:3 Comment(1)
This is the one.Witt
M
11
try:
    whatever()
except:
    # this will catch any exception or error

It is worth mentioning this is not proper Python coding. This will catch also many errors you might not want to catch.

Mattos answered 14/2, 2011 at 9:49 Comment(1)
just use except don't cach all exceptions as mentionned in some other answers. You have to use BaseException for this purpose but as you said, nobody should catch all exceptions like this. I guess it's ok for a start if the goal is to add more granular except during development but I don't think it will be...Hymnody
L
8

First of all, there are exceptions that you want them to break your code (as when this error happens your code will not function anyways!) and exceptions you want to capture silently/smoothly. Try differentiating them. You may not want to capture all exceptions there are!

Second, instead of capturing everything, you could take the time and go through the logs of your process. Let's say you are getting a different/third-party exception, for example from a cloud service provider like GCP. In the logs, you could find the exception you are getting. Then, you could do something like this:

from google.api_core.exceptions import ServiceUnavailable, RetryError

for i in range(10):
   try:
      print("do something")

   except ValueError:
      print("I know this might happen for now at times! skipping this and continuing with my loop"

   except ServiceUnavailable:
      print("our connection to a service (e.g. logging) of gcp has failed")
      print("initializing the cloud logger again and try continuing ...") 

   except RetryError:
      print("gcp connection retry failed. breaking the loop. try again later!)
      break

For the rest (errors that might or might not happen), I am leaving room for my code to crash if I get an unexpected exception! This way I could understand what is going on and improve my code by capturing edge cases.

If you want this to never crash for some reason, for example if it is a code embedded in a remote hardware that you cannot easily access, you can add a generic exception catcher at the end:

except Exception as e:
   print(f"something went wrong! - {e}")

You can also take a look at Python 3 exception hierarchy here. The difference between Exception and BaseException is that, Exception will not catch SystemExit, KeyboardInterrupt, or GeneratorExit

Lifeordeath answered 8/2, 2022 at 9:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.