New Exception Hierarchy In Python 3.3+

Working with the new stable version of Python 3.3, I stumbled upon the new exception hierarchy. Specifically, I was working on some file-related routines and found in the release notes, that for this domain a new set of exceptions is introduced and that IOError is now OSError.

Things are simple for code that will only run in Python 3.3 and above:

try:
    open("/tmp/i_am_not_here", "r")
except OSError as e:
    print("Caught:", e)

But what if the program also must run with Python 3.2 and before? Clearly the above code will not catch the exception raised there, because it is an IOError. And IOError in the old hierarchy is a sibling of OSError.

In Python 3.3, the documentation for “OSError“ states:

Changed in version 3.3: EnvironmentError, IOError, WindowsError, VMSError,
socket.error, select.error and mmap.error have been merged into OSError.

What do they mean by “have been merged into OSError”? Are IOError and OSError treated the same in Python 3.3+?

Yes. They are literally identical:

Python 2.7.3 (default, Sep  9 2012, 17:41:34)
[GCC 4.7.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> IOError == OSError
False

Python 3.3.0 (default, Sep 29 2012, 11:14:25)
[GCC 4.7.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> IOError == OSError
True

So, in code that must run in Python 3.3 and versions before, we must use IOError:

from __future__ import print_function
try:
    open("/tmp/i_am_not_here", "r")
except IOError as e:
    print("Caught:", e)

Let’s compare the changes in hierarchy between Python 2.7, 3.2 and 3.3:

static/images/python_exceptions1.png

Unfortunately, this depiction is not too helpful, because there is a change between Python 2.7 and 3.2 that affects almost all exceptions: In Python 2.7, all exceptions are children of StandardError, and from Python 3 on they descend directly from Exception.

If we concentrate upon the exceptions, the image is clearer. Here are the changes between Python 2.7, 3.2, 3.3 and 3.4 (dev) [1]

static/images/python_exceptions2.png
[1]I enclosed 3.4 because its documentation of OSError says “Changed in version 3.4.”, but I cannot see the difference to 3.3.