8.Errors and Exceptions

Until now error messages haven’t been more than mentioned, but if you have triedout the examples you have probably seen some. There are (at least) twodistinguishable kinds of errors:syntax errors andexceptions.

8.1.Syntax Errors

Syntax errors, also known as parsing errors, are perhaps the most common kind ofcomplaint you get while you are still learning Python:

>>>whileTrueprint('Hello world')  File"<stdin>", line1whileTrueprint('Hello world')^SyntaxError:invalid syntax

The parser repeats the offending line and displays a little ‘arrow’ pointing atthe earliest point in the line where the error was detected. The error iscaused by (or at least detected at) the tokenpreceding the arrow: in theexample, the error is detected at the functionprint(), since a colon(':') is missing before it. File name and line number are printed so youknow where to look in case the input came from a script.

8.2.Exceptions

Even if a statement or expression is syntactically correct, it may cause anerror when an attempt is made to execute it. Errors detected during executionare calledexceptions and are not unconditionally fatal: you will soon learnhow to handle them in Python programs. Most exceptions are not handled byprograms, however, and result in error messages as shown here:

>>>10*(1/0)Traceback (most recent call last):  File"<stdin>", line1, in<module>ZeroDivisionError:division by zero>>>4+spam*3Traceback (most recent call last):  File"<stdin>", line1, in<module>NameError:name 'spam' is not defined>>>'2'+2Traceback (most recent call last):  File"<stdin>", line1, in<module>TypeError:can only concatenate str (not "int") to str

The last line of the error message indicates what happened. Exceptions come indifferent types, and the type is printed as part of the message: the types inthe example areZeroDivisionError,NameError andTypeError.The string printed as the exception type is the name of the built-in exceptionthat occurred. This is true for all built-in exceptions, but need not be truefor user-defined exceptions (although it is a useful convention). Standardexception names are built-in identifiers (not reserved keywords).

The rest of the line provides detail based on the type of exception and whatcaused it.

The preceding part of the error message shows the context where the exceptionoccurred, in the form of a stack traceback. In general it contains a stacktraceback listing source lines; however, it will not display lines read fromstandard input.

Built-in Exceptions lists the built-in exceptions and their meanings.

8.3.Handling Exceptions

It is possible to write programs that handle selected exceptions. Look at thefollowing example, which asks the user for input until a valid integer has beenentered, but allows the user to interrupt the program (usingControl-C orwhatever the operating system supports); note that a user-generated interruptionis signalled by raising theKeyboardInterrupt exception.

>>>whileTrue:...try:...x=int(input("Please enter a number: "))...break...exceptValueError:...print("Oops!  That was no valid number.  Try again...")...

Thetry statement works as follows.

  • First, thetry clause (the statement(s) between thetry andexcept keywords) is executed.

  • If no exception occurs, theexcept clause is skipped and execution of thetry statement is finished.

  • If an exception occurs during execution of the try clause, the rest of theclause is skipped. Then if its type matches the exception named after theexcept keyword, the except clause is executed, and then executioncontinues after thetry statement.

  • If an exception occurs which does not match the exception named in the exceptclause, it is passed on to outertry statements; if no handler isfound, it is anunhandled exception and execution stops with a message asshown above.

Atry statement may have more than one except clause, to specifyhandlers for different exceptions. At most one handler will be executed.Handlers only handle exceptions that occur in the corresponding try clause, notin other handlers of the sametry statement. An except clause mayname multiple exceptions as a parenthesized tuple, for example:

...except(RuntimeError,TypeError,NameError):...pass

A class in anexcept clause is compatible with an exception if it isthe same class or a base class thereof (but not the other way around — anexcept clause listing a derived class is not compatible with a base class). Forexample, the following code will print B, C, D in that order:

classB(Exception):passclassC(B):passclassD(C):passforclsin[B,C,D]:try:raisecls()exceptD:print("D")exceptC:print("C")exceptB:print("B")

Note that if the except clauses were reversed (withexceptB first), itwould have printed B, B, B — the first matching except clause is triggered.

The last except clause may omit the exception name(s), to serve as a wildcard.Use this with extreme caution, since it is easy to mask a real programming errorin this way! It can also be used to print an error message and then re-raisethe exception (allowing a caller to handle the exception as well):

importsystry:f=open('myfile.txt')s=f.readline()i=int(s.strip())exceptOSErroraserr:print("OS error:{0}".format(err))exceptValueError:print("Could not convert data to an integer.")except:print("Unexpected error:",sys.exc_info()[0])raise

Thetryexcept statement has an optionalelseclause, which, when present, must follow all except clauses. It is useful forcode that must be executed if the try clause does not raise an exception. Forexample:

forarginsys.argv[1:]:try:f=open(arg,'r')exceptOSError:print('cannot open',arg)else:print(arg,'has',len(f.readlines()),'lines')f.close()

The use of theelse clause is better than adding additional code tothetry clause because it avoids accidentally catching an exceptionthat wasn’t raised by the code being protected by thetryexcept statement.

When an exception occurs, it may have an associated value, also known as theexception’sargument. The presence and type of the argument depend on theexception type.

The except clause may specify a variable after the exception name. Thevariable is bound to an exception instance with the arguments stored ininstance.args. For convenience, the exception instance defines__str__() so the arguments can be printed directly without having toreference.args. One may also instantiate an exception first beforeraising it and add any attributes to it as desired.

>>>try:...raiseException('spam','eggs')...exceptExceptionasinst:...print(type(inst))# the exception instance...print(inst.args)# arguments stored in .args...print(inst)# __str__ allows args to be printed directly,...# but may be overridden in exception subclasses...x,y=inst.args# unpack args...print('x =',x)...print('y =',y)...<class 'Exception'>('spam', 'eggs')('spam', 'eggs')x = spamy = eggs

If an exception has arguments, they are printed as the last part (‘detail’) ofthe message for unhandled exceptions.

Exception handlers don’t just handle exceptions if they occur immediately in thetry clause, but also if they occur inside functions that are called (evenindirectly) in the try clause. For example:

>>>defthis_fails():...x=1/0...>>>try:...this_fails()...exceptZeroDivisionErroraserr:...print('Handling run-time error:',err)...Handling run-time error: division by zero

8.4.Raising Exceptions

Theraise statement allows the programmer to force a specifiedexception to occur. For example:

>>>raiseNameError('HiThere')Traceback (most recent call last):  File"<stdin>", line1, in<module>NameError:HiThere

The sole argument toraise indicates the exception to be raised.This must be either an exception instance or an exception class (a class thatderives fromException). If an exception class is passed, it willbe implicitly instantiated by calling its constructor with no arguments:

raiseValueError# shorthand for 'raise ValueError()'

If you need to determine whether an exception was raised but don’t intend tohandle it, a simpler form of theraise statement allows you tore-raise the exception:

>>>try:...raiseNameError('HiThere')...exceptNameError:...print('An exception flew by!')...raise...An exception flew by!Traceback (most recent call last):  File"<stdin>", line2, in<module>NameError:HiThere

8.5.Exception Chaining

Theraise statement allows an optionalfrom which enableschaining exceptions. For example:

# exc must be exception instance or None.raiseRuntimeErrorfromexc

This can be useful when you are transforming exceptions. For example:

>>>deffunc():...raiseIOError...>>>try:...func()...exceptIOErrorasexc:...raiseRuntimeError('Failed to open database')fromexc...Traceback (most recent call last):  File"<stdin>", line2, in<module>  File"<stdin>", line2, infuncOSErrorThe above exception was the direct cause of the following exception:Traceback (most recent call last):  File"<stdin>", line4, in<module>RuntimeError:Failed to open database

Exception chaining happens automatically when an exception is raised inside anexcept orfinally section. Exception chaining can bedisabled by usingfromNone idiom:

>>>try:...open('database.sqlite')...exceptOSError:...raiseRuntimeErrorfromNone...Traceback (most recent call last):  File"<stdin>", line4, in<module>RuntimeError

For more information about chaining mechanics, seeBuilt-in Exceptions.

8.6.User-defined Exceptions

Programs may name their own exceptions by creating a new exception class (seeClasses for more about Python classes). Exceptions should typicallybe derived from theException class, either directly or indirectly.

Exception classes can be defined which do anything any other class can do, butare usually kept simple, often only offering a number of attributes that allowinformation about the error to be extracted by handlers for the exception.

Most exceptions are defined with names that end in “Error”, similar to thenaming of the standard exceptions.

Many standard modules define their own exceptions to report errors that mayoccur in functions they define. More information on classes is presented inchapterClasses.

8.7.Defining Clean-up Actions

Thetry statement has another optional clause which is intended todefine clean-up actions that must be executed under all circumstances. Forexample:

>>>try:...raiseKeyboardInterrupt...finally:...print('Goodbye, world!')...Goodbye, world!Traceback (most recent call last):  File"<stdin>", line2, in<module>KeyboardInterrupt

If afinally clause is present, thefinallyclause will execute as the last task before thetrystatement completes. Thefinally clause runs whether ornot thetry statement produces an exception. The followingpoints discuss more complex cases when an exception occurs:

  • If an exception occurs during execution of thetryclause, the exception may be handled by anexceptclause. If the exception is not handled by anexceptclause, the exception is re-raised after thefinallyclause has been executed.

  • An exception could occur during execution of anexceptorelse clause. Again, the exception is re-raised afterthefinally clause has been executed.

  • If thefinally clause executes abreak,continue orreturn statement, exceptions are notre-raised.

  • If thetry statement reaches abreak,continue orreturn statement, thefinally clause will execute just prior to thebreak,continue orreturnstatement’s execution.

  • If afinally clause includes areturnstatement, the returned value will be the one from thefinally clause’sreturn statement, not thevalue from thetry clause’sreturnstatement.

For example:

>>>defbool_return():...try:...returnTrue...finally:...returnFalse...>>>bool_return()False

A more complicated example:

>>>defdivide(x,y):...try:...result=x/y...exceptZeroDivisionError:...print("division by zero!")...else:...print("result is",result)...finally:...print("executing finally clause")...>>>divide(2,1)result is 2.0executing finally clause>>>divide(2,0)division by zero!executing finally clause>>>divide("2","1")executing finally clauseTraceback (most recent call last):  File"<stdin>", line1, in<module>  File"<stdin>", line3, individeTypeError:unsupported operand type(s) for /: 'str' and 'str'

As you can see, thefinally clause is executed in any event. TheTypeError raised by dividing two strings is not handled by theexcept clause and therefore re-raised after thefinallyclause has been executed.

In real world applications, thefinally clause is useful forreleasing external resources (such as files or network connections), regardlessof whether the use of the resource was successful.

8.8.Predefined Clean-up Actions

Some objects define standard clean-up actions to be undertaken when the objectis no longer needed, regardless of whether or not the operation using the objectsucceeded or failed. Look at the following example, which tries to open a fileand print its contents to the screen.

forlineinopen("myfile.txt"):print(line,end="")

The problem with this code is that it leaves the file open for an indeterminateamount of time after this part of the code has finished executing.This is not an issue in simple scripts, but can be a problem for largerapplications. Thewith statement allows objects like files to beused in a way that ensures they are always cleaned up promptly and correctly.

withopen("myfile.txt")asf:forlineinf:print(line,end="")

After the statement is executed, the filef is always closed, even if aproblem was encountered while processing the lines. Objects which, like files,provide predefined clean-up actions will indicate this in their documentation.