Python 2/3 compatible code to create an exception
Six provides simple utilities for transferring the differences between Python 2 and Python 3. It is designed to support codebases that run on both Python 2 and 3 unchanged. six consists of only one python, so copy painlessly to the project. http://pythonhosted.org/six/
from six import reraise as raise_
Convert from Python 2 to Python 3.
You can make a copy of Python 3 code using 2to3.
2to3 is a Python program that reads the source code of Python 2.x and uses a series of fixers to convert it to actual Python 3.x code. the standard library contains a rich set of latches that will process almost all the code. 2to3, which supports the lib2to3 library, however, is also a flexible and shared library, so you can write your own latches for 2to3. lib2to3 can also be adapted to user applications in which Python code needs to be edited automatically.
...
2to3 can also write the necessary changes directly to the source file. (Of course, a backup copy of the original will also be made, if only -n is also given.) Recording changes back is enabled using the -w flag:
$ 2to3 -w example.py
(from https://docs.python.org/3.0/library/2to3.html )
Python Version Definition
If you want to determine the version of python, I recommend:
PY2 = sys.version_info.major == 2 PY3 = sys.version_info.major == 3 # or import six # Python 2 / 3 compatability module six.PY2 # is this Python 2 six.PY3 # is this Python 3
Version Based Python Solutions
Remember that earlier versions of Python 2 will be different from 2.7. I like to plan all unforeseen situations, so the following code will throw an exception (litteraly) if you are using a version of Python prior to version 2.7.
# If you want to use and if/then/else block... import sys major = sys.version_info.major minor = sys.version_info.minor if major == 3: # Python 3 exception handling print("Do something with Python {}.{} code.".format(major, minor)) elif major == 2: # Python 2 exception handling if minor >= 7: # Python 2.7 print("Do something with Python {}.{} code.".format(major, minor)) else: # Python 2.6 and earlier exception handling assert minor >= 2, "Please use Python 2.7 or later, not {}.{}.".format(major,minor) else: assert major >= 2, "Sorry, I'm not writing code for pre-version 2 Python. It just ain't happening. You are using Python {}.{}.".format(major,minor) assert major > 3, "I can't handle Python versions that haven't been written yet.. You are using Python {}.{}.".format(major,minor)
Exception handling in Python 2 and 3
python-future is the missing level of compatibility between Python 2 and Python 3. It allows you to use one pure Python 3.x-compatible codebase to support both Python 2 and Python 3 with minimal overhead.
It provides future and past packages with backports and forward ports functions from Python 3 and 2. It also comes with futurization and pasteurization, customization of 2to3-based scripts that will help you convert either Py2 or Py3 code to easily support both Python 2 and and 3 in a one-time pure code base of type Py3, module modulo. http://python-future.org/overview.html
See the documentation for the upcoming python module at http://python-future.org/ . The following is a copy of the “Exceptions and Corrections Fixes” sections on the page.
import future
Python 2 only:
raise ValueError, "dodgy value"
Python 2 and 3:
raise ValueError("dodgy value") Raising exceptions with a traceback:
Python 2 only:
traceback = sys.exc_info()[2] raise ValueError, "dodgy value", traceback
Python 3 only:
raise ValueError("dodgy value").with_traceback()
Python 2 and 3: option 1
from six import reraise as raise_
Python 2 and 3: option 2
from future.utils import raise_with_traceback raise_with_traceback(ValueError("dodgy value")) Exception chaining (PEP 3134):
Setup:
class DatabaseError(Exception): pass
Python 3 only
class FileDatabase: def __init__(self, filename): try: self.file = open(filename) except IOError as exc: raise DatabaseError('failed to open') from exc
Python 2 and 3:
from future.utils import raise_from class FileDatabase: def __init__(self, filename): try: self.file = open(filename) except IOError as exc: raise_from(DatabaseError('failed to open'), exc)
Testing above:
try: fd = FileDatabase('non_existent_file.txt') except Exception as e: assert isinstance(e.__cause__, IOError)
Python 2 only:
try: ... except ValueError, e: ...
Python 2 and 3:
try: ... except ValueError as e: ...