| 1 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> |
| 2 | <html> |
| 3 | <head> |
| 4 | <link rel="STYLESHEET" href="api.css" type='text/css' /> |
| 5 | <link rel="SHORTCUT ICON" href="../icons/pyfav.png" type="image/png" /> |
| 6 | <link rel='start' href='../index.html' title='Python Documentation Index' /> |
| 7 | <link rel="first" href="api.html" title='Python/C API Reference Manual' /> |
| 8 | <link rel='contents' href='contents.html' title="Contents" /> |
| 9 | <link rel='index' href='genindex.html' title='Index' /> |
| 10 | <link rel='last' href='about.html' title='About this document...' /> |
| 11 | <link rel='help' href='about.html' title='About this document...' /> |
| 12 | <link rel="next" href="embedding.html" /> |
| 13 | <link rel="prev" href="objects.html" /> |
| 14 | <link rel="parent" href="intro.html" /> |
| 15 | <link rel="next" href="embedding.html" /> |
| 16 | <meta name='aesop' content='information' /> |
| 17 | <title>1.3 Exceptions </title> |
| 18 | </head> |
| 19 | <body> |
| 20 | <DIV CLASS="navigation"> |
| 21 | <div id='top-navigation-panel' xml:id='top-navigation-panel'> |
| 22 | <table align="center" width="100%" cellpadding="0" cellspacing="2"> |
| 23 | <tr> |
| 24 | <td class='online-navigation'><a rel="prev" title="1.2.2 Types" |
| 25 | href="types.html"><img src='../icons/previous.png' |
| 26 | border='0' height='32' alt='Previous Page' width='32' /></A></td> |
| 27 | <td class='online-navigation'><a rel="parent" title="1. Introduction" |
| 28 | href="intro.html"><img src='../icons/up.png' |
| 29 | border='0' height='32' alt='Up One Level' width='32' /></A></td> |
| 30 | <td class='online-navigation'><a rel="next" title="1.4 Embedding Python" |
| 31 | href="embedding.html"><img src='../icons/next.png' |
| 32 | border='0' height='32' alt='Next Page' width='32' /></A></td> |
| 33 | <td align="center" width="100%">Python/C API Reference Manual</td> |
| 34 | <td class='online-navigation'><a rel="contents" title="Table of Contents" |
| 35 | href="contents.html"><img src='../icons/contents.png' |
| 36 | border='0' height='32' alt='Contents' width='32' /></A></td> |
| 37 | <td class='online-navigation'><img src='../icons/blank.png' |
| 38 | border='0' height='32' alt='' width='32' /></td> |
| 39 | <td class='online-navigation'><a rel="index" title="Index" |
| 40 | href="genindex.html"><img src='../icons/index.png' |
| 41 | border='0' height='32' alt='Index' width='32' /></A></td> |
| 42 | </tr></table> |
| 43 | <div class='online-navigation'> |
| 44 | <b class="navlabel">Previous:</b> |
| 45 | <a class="sectref" rel="prev" href="types.html">1.2.2 Types</A> |
| 46 | <b class="navlabel">Up:</b> |
| 47 | <a class="sectref" rel="parent" href="intro.html">1. Introduction</A> |
| 48 | <b class="navlabel">Next:</b> |
| 49 | <a class="sectref" rel="next" href="embedding.html">1.4 Embedding Python</A> |
| 50 | </div> |
| 51 | <hr /></div> |
| 52 | </DIV> |
| 53 | <!--End of Navigation Panel--> |
| 54 | |
| 55 | <H1><A NAME="SECTION003300000000000000000"></A><A NAME="exceptions"></A> |
| 56 | <BR> |
| 57 | 1.3 Exceptions |
| 58 | </H1> |
| 59 | |
| 60 | <P> |
| 61 | The Python programmer only needs to deal with exceptions if specific |
| 62 | error handling is required; unhandled exceptions are automatically |
| 63 | propagated to the caller, then to the caller's caller, and so on, until |
| 64 | they reach the top-level interpreter, where they are reported to the |
| 65 | user accompanied by a stack traceback. |
| 66 | |
| 67 | <P> |
| 68 | For C programmers, however, error checking always has to be explicit. |
| 69 | All functions in the Python/C API can raise exceptions, unless an |
| 70 | explicit claim is made otherwise in a function's documentation. In |
| 71 | general, when a function encounters an error, it sets an exception, |
| 72 | discards any object references that it owns, and returns an |
| 73 | error indicator -- usually <tt class="constant">NULL</tt> or <code>-1</code>. A few functions |
| 74 | return a Boolean true/false result, with false indicating an error. |
| 75 | Very few functions return no explicit error indicator or have an |
| 76 | ambiguous return value, and require explicit testing for errors with |
| 77 | <tt class="cfunction">PyErr_Occurred()</tt><a id='l2h-20' xml:id='l2h-20'></a>. |
| 78 | |
| 79 | <P> |
| 80 | Exception state is maintained in per-thread storage (this is |
| 81 | equivalent to using global storage in an unthreaded application). A |
| 82 | thread can be in one of two states: an exception has occurred, or not. |
| 83 | The function <tt class="cfunction">PyErr_Occurred()</tt> can be used to check for |
| 84 | this: it returns a borrowed reference to the exception type object |
| 85 | when an exception has occurred, and <tt class="constant">NULL</tt> otherwise. There are a |
| 86 | number of functions to set the exception state: |
| 87 | <tt class="cfunction">PyErr_SetString()</tt><a id='l2h-21' xml:id='l2h-21'></a> is the most |
| 88 | common (though not the most general) function to set the exception |
| 89 | state, and <tt class="cfunction">PyErr_Clear()</tt><a id='l2h-22' xml:id='l2h-22'></a> clears the |
| 90 | exception state. |
| 91 | |
| 92 | <P> |
| 93 | The full exception state consists of three objects (all of which can |
| 94 | be <tt class="constant">NULL</tt>): the exception type, the corresponding exception |
| 95 | value, and the traceback. These have the same meanings as the Python |
| 96 | <a id='l2h-17' xml:id='l2h-17'></a>objects <code>sys.exc_type</code>, <code>sys.exc_value</code>, and |
| 97 | <code>sys.exc_traceback</code>; however, they are not the same: the Python |
| 98 | objects represent the last exception being handled by a Python |
| 99 | <tt class="keyword">try</tt> ... <tt class="keyword">except</tt> statement, while the C level |
| 100 | exception state only exists while an exception is being passed on |
| 101 | between C functions until it reaches the Python bytecode interpreter's |
| 102 | main loop, which takes care of transferring it to <code>sys.exc_type</code> |
| 103 | and friends. |
| 104 | |
| 105 | <P> |
| 106 | Note that starting with Python 1.5, the preferred, thread-safe way to |
| 107 | access the exception state from Python code is to call the function |
| 108 | <a id='l2h-19' xml:id='l2h-19'></a><tt class="function">sys.exc_info()</tt>, which returns the per-thread exception state |
| 109 | for Python code. Also, the semantics of both ways to access the |
| 110 | exception state have changed so that a function which catches an |
| 111 | exception will save and restore its thread's exception state so as to |
| 112 | preserve the exception state of its caller. This prevents common bugs |
| 113 | in exception handling code caused by an innocent-looking function |
| 114 | overwriting the exception being handled; it also reduces the often |
| 115 | unwanted lifetime extension for objects that are referenced by the |
| 116 | stack frames in the traceback. |
| 117 | |
| 118 | <P> |
| 119 | As a general principle, a function that calls another function to |
| 120 | perform some task should check whether the called function raised an |
| 121 | exception, and if so, pass the exception state on to its caller. It |
| 122 | should discard any object references that it owns, and return an |
| 123 | error indicator, but it should <em>not</em> set another exception -- |
| 124 | that would overwrite the exception that was just raised, and lose |
| 125 | important information about the exact cause of the error. |
| 126 | |
| 127 | <P> |
| 128 | A simple example of detecting exceptions and passing them on is shown |
| 129 | in the <tt class="cfunction">sum_sequence()</tt><a id='l2h-23' xml:id='l2h-23'></a> example |
| 130 | above. It so happens that that example doesn't need to clean up any |
| 131 | owned references when it detects an error. The following example |
| 132 | function shows some error cleanup. First, to remind you why you like |
| 133 | Python, we show the equivalent Python code: |
| 134 | |
| 135 | <P> |
| 136 | <div class="verbatim"><pre> |
| 137 | def incr_item(dict, key): |
| 138 | try: |
| 139 | item = dict[key] |
| 140 | except KeyError: |
| 141 | item = 0 |
| 142 | dict[key] = item + 1 |
| 143 | </pre></div> |
| 144 | |
| 145 | <P> |
| 146 | Here is the corresponding C code, in all its glory: |
| 147 | |
| 148 | <P> |
| 149 | <div class="verbatim"><pre> |
| 150 | int |
| 151 | incr_item(PyObject *dict, PyObject *key) |
| 152 | { |
| 153 | /* Objects all initialized to NULL for Py_XDECREF */ |
| 154 | PyObject *item = NULL, *const_one = NULL, *incremented_item = NULL; |
| 155 | int rv = -1; /* Return value initialized to -1 (failure) */ |
| 156 | |
| 157 | item = PyObject_GetItem(dict, key); |
| 158 | if (item == NULL) { |
| 159 | /* Handle KeyError only: */ |
| 160 | if (!PyErr_ExceptionMatches(PyExc_KeyError)) |
| 161 | goto error; |
| 162 | |
| 163 | /* Clear the error and use zero: */ |
| 164 | PyErr_Clear(); |
| 165 | item = PyInt_FromLong(0L); |
| 166 | if (item == NULL) |
| 167 | goto error; |
| 168 | } |
| 169 | const_one = PyInt_FromLong(1L); |
| 170 | if (const_one == NULL) |
| 171 | goto error; |
| 172 | |
| 173 | incremented_item = PyNumber_Add(item, const_one); |
| 174 | if (incremented_item == NULL) |
| 175 | goto error; |
| 176 | |
| 177 | if (PyObject_SetItem(dict, key, incremented_item) < 0) |
| 178 | goto error; |
| 179 | rv = 0; /* Success */ |
| 180 | /* Continue with cleanup code */ |
| 181 | |
| 182 | error: |
| 183 | /* Cleanup code, shared by success and failure path */ |
| 184 | |
| 185 | /* Use Py_XDECREF() to ignore NULL references */ |
| 186 | Py_XDECREF(item); |
| 187 | Py_XDECREF(const_one); |
| 188 | Py_XDECREF(incremented_item); |
| 189 | |
| 190 | return rv; /* -1 for error, 0 for success */ |
| 191 | } |
| 192 | </pre></div> |
| 193 | |
| 194 | <P> |
| 195 | This example represents an endorsed use of the <tt class="keyword">goto</tt> statement |
| 196 | in C! It illustrates the use of |
| 197 | <tt class="cfunction">PyErr_ExceptionMatches()</tt><a id='l2h-24' xml:id='l2h-24'></a> and |
| 198 | <tt class="cfunction">PyErr_Clear()</tt><a id='l2h-25' xml:id='l2h-25'></a> to |
| 199 | handle specific exceptions, and the use of |
| 200 | <tt class="cfunction">Py_XDECREF()</tt><a id='l2h-26' xml:id='l2h-26'></a> to |
| 201 | dispose of owned references that may be <tt class="constant">NULL</tt> (note the |
| 202 | "<tt class="character">X</tt>" in the name; <tt class="cfunction">Py_DECREF()</tt> would crash when |
| 203 | confronted with a <tt class="constant">NULL</tt> reference). It is important that the |
| 204 | variables used to hold owned references are initialized to <tt class="constant">NULL</tt> for |
| 205 | this to work; likewise, the proposed return value is initialized to |
| 206 | <code>-1</code> (failure) and only set to success after the final call made |
| 207 | is successful. |
| 208 | |
| 209 | <P> |
| 210 | |
| 211 | <DIV CLASS="navigation"> |
| 212 | <div class='online-navigation'> |
| 213 | <p></p><hr /> |
| 214 | <table align="center" width="100%" cellpadding="0" cellspacing="2"> |
| 215 | <tr> |
| 216 | <td class='online-navigation'><a rel="prev" title="1.2.2 Types" |
| 217 | href="types.html"><img src='../icons/previous.png' |
| 218 | border='0' height='32' alt='Previous Page' width='32' /></A></td> |
| 219 | <td class='online-navigation'><a rel="parent" title="1. Introduction" |
| 220 | href="intro.html"><img src='../icons/up.png' |
| 221 | border='0' height='32' alt='Up One Level' width='32' /></A></td> |
| 222 | <td class='online-navigation'><a rel="next" title="1.4 Embedding Python" |
| 223 | href="embedding.html"><img src='../icons/next.png' |
| 224 | border='0' height='32' alt='Next Page' width='32' /></A></td> |
| 225 | <td align="center" width="100%">Python/C API Reference Manual</td> |
| 226 | <td class='online-navigation'><a rel="contents" title="Table of Contents" |
| 227 | href="contents.html"><img src='../icons/contents.png' |
| 228 | border='0' height='32' alt='Contents' width='32' /></A></td> |
| 229 | <td class='online-navigation'><img src='../icons/blank.png' |
| 230 | border='0' height='32' alt='' width='32' /></td> |
| 231 | <td class='online-navigation'><a rel="index" title="Index" |
| 232 | href="genindex.html"><img src='../icons/index.png' |
| 233 | border='0' height='32' alt='Index' width='32' /></A></td> |
| 234 | </tr></table> |
| 235 | <div class='online-navigation'> |
| 236 | <b class="navlabel">Previous:</b> |
| 237 | <a class="sectref" rel="prev" href="types.html">1.2.2 Types</A> |
| 238 | <b class="navlabel">Up:</b> |
| 239 | <a class="sectref" rel="parent" href="intro.html">1. Introduction</A> |
| 240 | <b class="navlabel">Next:</b> |
| 241 | <a class="sectref" rel="next" href="embedding.html">1.4 Embedding Python</A> |
| 242 | </div> |
| 243 | </div> |
| 244 | <hr /> |
| 245 | <span class="release-info">Release 2.4.2, documentation updated on 28 September 2005.</span> |
| 246 | </DIV> |
| 247 | <!--End of Navigation Panel--> |
| 248 | <ADDRESS> |
| 249 | See <i><a href="about.html">About this document...</a></i> for information on suggesting changes. |
| 250 | </ADDRESS> |
| 251 | </BODY> |
| 252 | </HTML> |