This is the Python 2 syntax, note the commas ,
on the raise
and except
lines:
try:
raise IOError, "input/output error"
except IOError, exc:
print exc
In Python 3, the ,
syntax is dropped and replaced by parenthesis and the as
keyword:
try:
raise IOError("input/output error")
except IOError as exc:
print(exc)
For backwards compatibility, the Python 3 syntax is also available in Python 2.6 onwards, so it should be used for all new code that does not need to be compatible with previous versions.
Python 3 also adds exception chaining, wherein you can signal that some other exception was the cause for this exception. For example
try:
file = open('database.db')
except FileNotFoundError as e:
raise DatabaseError('Cannot open {}') from e
The exception raised in the except
statement is of type DatabaseError
, but the original exception is marked as the __cause__
attribute of that exception. When the traceback is displayed, the original exception will also be displayed in the traceback:
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
FileNotFoundError
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
DatabaseError('Cannot open database.db')
If you throw in an except
block without explicit chaining:
try:
file = open('database.db')
except FileNotFoundError as e:
raise DatabaseError('Cannot open {}')
The traceback is
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
FileNotFoundError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
DatabaseError('Cannot open database.db')
Neither one is supported in Python 2.x; the original exception and its traceback will be lost if another exception is raised in the except block. The following code can be used for compatibility:
import sys
import traceback
try:
funcWithError()
except:
sys_vers = getattr(sys, 'version_info', (0,))
if sys_vers < (3, 0):
traceback.print_exc()
raise Exception("new exception")
To "forget" the previously thrown exception, use raise from None
try:
file = open('database.db')
except FileNotFoundError as e:
raise DatabaseError('Cannot open {}') from None
Now the traceback would simply be
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
DatabaseError('Cannot open database.db')
Or in order to make it compatible with both Python 2 and 3 you may use the six package like so:
import six
try:
file = open('database.db')
except FileNotFoundError as e:
six.raise_from(DatabaseError('Cannot open {}'), None)