5

I've been programming in Python for a while now, but my efforts have been mainly creating small utility scripts. I think that Python is a great language because its fun and it makes it easy to write clean code.

However, there is one annoyance I haven't found a cure for: Due to it's dynamic nature, exceptions can be thrown from various sources and they will kill your program if they're not caught. To me, this is a pain for "largish" programs.

In Java (not that I know Java better than I know Python), the compiler actually statically enforces the handling of exceptions so that all possible exceptions are caught. Is it possible to achieve the same with Python?

DavidRR
  • 18,291
  • 25
  • 109
  • 191
lang2
  • 11,433
  • 18
  • 83
  • 133
  • There is a good blog post about this that discusses pros and cons of different methods for catching exceptions in python: http://blog.ianbicking.org/good-catch-all-exceptions.html – Hunter McMillen Jul 25 '11 at 14:06
  • 3
    Even in Java, the compiler doesn't look for `RuntimeException` and its subclasses. And that's a good thing - you don't want to write `except (OutOfMemoryException e) { /* well, we're screwed */; raise e; }` in every single method, do you? –  Jul 25 '11 at 14:36
  • Related: [Logging uncaught exceptions in Python](http://stackoverflow.com/q/6234405/1497596) – DavidRR Mar 12 '15 at 13:33

5 Answers5

4

You can catch all exceptions with the simple except: statement. But this is considered dangerous, since this also covers syntactical errors.

The best practice is to cover all possible and expected exception types with one except clause. Consider the following example:

except (IOError, ArgumentError), e:
    print(e)

This example catches the two expected exceptions, all others will fall through and will be written to stderr.

Constantinius
  • 34,183
  • 8
  • 77
  • 85
  • 1
    Note that in Python 3 it's "as e", not ", e". – JAB Jul 25 '11 at 14:10
  • 4
    `except` doesnt catch SyntaxErrors – Jochen Ritzel Jul 25 '11 at 14:31
  • 1
    But it does catch genuine bugs like variable/member name typos (`NameError`, `AttributeError`) though, and (if swallowing the exceptions, what OP seems to intend) prevents code higher up the call chain from actually handling (as opposed to ignoring) the error. –  Jul 25 '11 at 14:39
  • I don't think the OP is asking how to catch exceptions (the interpreter will tell you when your code breaks) but instead how to insure that code is correct. – Wilduck Jul 25 '11 at 15:03
  • @JAB: Note that "`as e`" syntax is also available in 2.7.9 (and possibly prior versions of 2.x). From the 2.7.9 tutorial, see [8.3. Handling Exceptions](https://docs.python.org/2.7/tutorial/errors.html#handling-exceptions). – DavidRR Mar 12 '15 at 13:45
2

So, others have answered with ways to generally catch exceptions. I'm going to take a slightly different bent. I think what you're asking about is how you can achieve the same sort of type safety that occurs in a statically typed language.

First off, you probably don't want to. One of python's advantages is duck typing. From Wikipedia:

duck typing is a style of dynamic typing in which an object's current set of methods and properties determines the valid semantics, rather than its inheritance from a particular class or implementation of a specific interface

The advantage of duck typing is that you don't have to do type checking, you can pass any object that has a given method.

However, you then have the problem: "How does one consistently check that my code will be correct without running it?" This is especially annoying when an error only occurs as an edge case. One good way to insure consistent behavior, even while changing your code base, is to write unit tests. Python has a number of different methods of implementing unit testing. The simplest is probably the doctest module. If you want something more powerful, however, there's also unittest, and the unittest compatible third-party framework nose.

The benefit of unit testing is that you can write them as you go, making sure to look for even the uncommon edge cases, and then run them any time you make a significant change to your program. Then, if the tests fail, you know you've broken something.

Wilduck
  • 13,822
  • 10
  • 58
  • 90
  • While I like your answer, I interpreted the OP's question more broadly. For instance, making sure that your program handles `IOError` (if it applies) has nothing to do with type safety. – DavidRR Mar 12 '15 at 13:18
1
try:
    # the body of your main loop or whatever
except Exception:
    # Import the traceback and system modules
    import traceback, sys
    # Prepare the arguments
    exc_type, exc_value, exc_traceback = sys.exc_info()
    # Print the exception. There are more args -- read the traceback docs!
    traceback.print_exception(exc_type, exc_value, exc_traceback)
    # This is where your house-cleaning code goes.

I use this for making sure things are left in a sane state after a crash. If your "graceful crash" code relies on whatever threw the exception... Just use this with caution ;)

1

Well, you could go with catching general exceptions but that's not considered good practice.

try:
    # Execute code here
except Exception:
    # Log error

The better way to do it is to catch specific exceptions you know are possible to happen, so you can find a specific way to deal with them. There is nothing worse than catching an exception you don't know.

Jon Martin
  • 3,252
  • 5
  • 29
  • 45
  • 3
    this won't catch `KeyboardInterrupt` in Python >= 2.5 – Roman Bodnarchuk Jul 25 '11 at 14:08
  • 1
    as said @Roman Bodnarchuk, `except Exception` will not catch some usefull exceptions like SystemExit, KeyboardInterrupt and GeneratorExit, to catch them all, use a pokeball (hem..), use a `except BaseException`. – Cédric Julien Jul 25 '11 at 18:25
1

You might want to look at sys.excepthook:

When an exception is raised and uncaught, the interpreter calls sys.excepthook with three arguments, the exception class, exception instance, and a traceback object. In an interactive session this happens just before control is returned to the prompt; in a Python program this happens just before the program exits. The handling of such top-level exceptions can be customized by assigning another three-argument function to sys.excepthook.

Example:

def except_hook(type, value, tback):
    # manage unhandled exception here
    sys.__excepthook__(type, value, tback) # then call the default handler - if you need to

sys.excepthook = except_hook
warvariuc
  • 57,116
  • 41
  • 173
  • 227