Commit | Line | Data |
---|---|---|
920dae64 AT |
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> |