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="tut.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="tut.html" title='Python Tutorial' /> | |
8 | <link rel='contents' href='node2.html' title="Contents" /> | |
9 | <link rel='index' href='node19.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="node11.html" /> | |
13 | <link rel="prev" href="node9.html" /> | |
14 | <link rel="parent" href="tut.html" /> | |
15 | <link rel="next" href="node11.html" /> | |
16 | <meta name='aesop' content='information' /> | |
17 | <title>8. Errors and 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="7. Input and Output" | |
25 | href="node9.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="Python Tutorial" | |
28 | href="tut.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="9. Classes" | |
31 | href="node11.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 Tutorial</td> | |
34 | <td class='online-navigation'><a rel="contents" title="Table of Contents" | |
35 | href="node2.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="node19.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="node9.html">7. Input and Output</A> | |
46 | <b class="navlabel">Up:</b> | |
47 | <a class="sectref" rel="parent" href="tut.html">Python Tutorial</A> | |
48 | <b class="navlabel">Next:</b> | |
49 | <a class="sectref" rel="next" href="node11.html">9. Classes</A> | |
50 | </div> | |
51 | <hr /></div> | |
52 | </DIV> | |
53 | <!--End of Navigation Panel--> | |
54 | <div class='online-navigation'> | |
55 | <!--Table of Child-Links--> | |
56 | <A NAME="CHILD_LINKS"><STRONG>Subsections</STRONG></a> | |
57 | ||
58 | <UL CLASS="ChildLinks"> | |
59 | <LI><A href="node10.html#SECTION0010100000000000000000">8.1 Syntax Errors</a> | |
60 | <LI><A href="node10.html#SECTION0010200000000000000000">8.2 Exceptions</a> | |
61 | <LI><A href="node10.html#SECTION0010300000000000000000">8.3 Handling Exceptions</a> | |
62 | <LI><A href="node10.html#SECTION0010400000000000000000">8.4 Raising Exceptions</a> | |
63 | <LI><A href="node10.html#SECTION0010500000000000000000">8.5 User-defined Exceptions</a> | |
64 | <LI><A href="node10.html#SECTION0010600000000000000000">8.6 Defining Clean-up Actions</a> | |
65 | </ul> | |
66 | <!--End of Table of Child-Links--> | |
67 | </div> | |
68 | <HR> | |
69 | ||
70 | <H1><A NAME="SECTION0010000000000000000000"></A><A NAME="errors"></A> | |
71 | <BR> | |
72 | 8. Errors and Exceptions | |
73 | </H1> | |
74 | ||
75 | <P> | |
76 | Until now error messages haven't been more than mentioned, but if you | |
77 | have tried out the examples you have probably seen some. There are | |
78 | (at least) two distinguishable kinds of errors: | |
79 | <em>syntax errors</em> and <em>exceptions</em>. | |
80 | ||
81 | <P> | |
82 | ||
83 | <H1><A NAME="SECTION0010100000000000000000"></A><A NAME="syntaxErrors"></A> | |
84 | <BR> | |
85 | 8.1 Syntax Errors | |
86 | </H1> | |
87 | ||
88 | <P> | |
89 | Syntax errors, also known as parsing errors, are perhaps the most common | |
90 | kind of complaint you get while you are still learning Python: | |
91 | ||
92 | <P> | |
93 | <div class="verbatim"><pre> | |
94 | >>> while True print 'Hello world' | |
95 | File "<stdin>", line 1, in ? | |
96 | while True print 'Hello world' | |
97 | ^ | |
98 | SyntaxError: invalid syntax | |
99 | </pre></div> | |
100 | ||
101 | <P> | |
102 | The parser repeats the offending line and displays a little `arrow' | |
103 | pointing at the earliest point in the line where the error was | |
104 | detected. The error is caused by (or at least detected at) the token | |
105 | <em>preceding</em> the arrow: in the example, the error is detected at | |
106 | the keyword <tt class="keyword">print</tt>, since a colon ("<tt class="character">:</tt>") is missing | |
107 | before it. File name and line number are printed so you know where to | |
108 | look in case the input came from a script. | |
109 | ||
110 | <P> | |
111 | ||
112 | <H1><A NAME="SECTION0010200000000000000000"></A><A NAME="exceptions"></A> | |
113 | <BR> | |
114 | 8.2 Exceptions | |
115 | </H1> | |
116 | ||
117 | <P> | |
118 | Even if a statement or expression is syntactically correct, it may | |
119 | cause an error when an attempt is made to execute it. | |
120 | Errors detected during execution are called <em>exceptions</em> and are | |
121 | not unconditionally fatal: you will soon learn how to handle them in | |
122 | Python programs. Most exceptions are not handled by programs, | |
123 | however, and result in error messages as shown here: | |
124 | ||
125 | <P> | |
126 | <div class="verbatim"><pre> | |
127 | >>> 10 * (1/0) | |
128 | Traceback (most recent call last): | |
129 | File "<stdin>", line 1, in ? | |
130 | ZeroDivisionError: integer division or modulo by zero | |
131 | >>> 4 + spam*3 | |
132 | Traceback (most recent call last): | |
133 | File "<stdin>", line 1, in ? | |
134 | NameError: name 'spam' is not defined | |
135 | >>> '2' + 2 | |
136 | Traceback (most recent call last): | |
137 | File "<stdin>", line 1, in ? | |
138 | TypeError: cannot concatenate 'str' and 'int' objects | |
139 | </pre></div> | |
140 | ||
141 | <P> | |
142 | The last line of the error message indicates what happened. | |
143 | Exceptions come in different types, and the type is printed as part of | |
144 | the message: the types in the example are | |
145 | <tt class="exception">ZeroDivisionError</tt>, <tt class="exception">NameError</tt> and | |
146 | <tt class="exception">TypeError</tt>. | |
147 | The string printed as the exception type is the name of the built-in | |
148 | exception that occurred. This is true for all built-in | |
149 | exceptions, but need not be true for user-defined exceptions (although | |
150 | it is a useful convention). | |
151 | Standard exception names are built-in identifiers (not reserved | |
152 | keywords). | |
153 | ||
154 | <P> | |
155 | The rest of the line provides detail based on the type of exception | |
156 | and what caused it. | |
157 | ||
158 | <P> | |
159 | The preceding part of the error message shows the context where the | |
160 | exception happened, in the form of a stack traceback. | |
161 | In general it contains a stack traceback listing source lines; however, | |
162 | it will not display lines read from standard input. | |
163 | ||
164 | <P> | |
165 | The <em class="citetitle"><a | |
166 | href="../lib/module-exceptions.html" | |
167 | title="Python Library | |
168 | Reference" | |
169 | >Python Library | |
170 | Reference</a></em> lists the built-in exceptions and their meanings. | |
171 | ||
172 | <P> | |
173 | ||
174 | <H1><A NAME="SECTION0010300000000000000000"></A><A NAME="handling"></A> | |
175 | <BR> | |
176 | 8.3 Handling Exceptions | |
177 | </H1> | |
178 | ||
179 | <P> | |
180 | It is possible to write programs that handle selected exceptions. | |
181 | Look at the following example, which asks the user for input until a | |
182 | valid integer has been entered, but allows the user to interrupt the | |
183 | program (using <kbd>Control-C</kbd> or whatever the operating system | |
184 | supports); note that a user-generated interruption is signalled by | |
185 | raising the <tt class="exception">KeyboardInterrupt</tt> exception. | |
186 | ||
187 | <P> | |
188 | <div class="verbatim"><pre> | |
189 | >>> while True: | |
190 | ... try: | |
191 | ... x = int(raw_input("Please enter a number: ")) | |
192 | ... break | |
193 | ... except ValueError: | |
194 | ... print "Oops! That was no valid number. Try again..." | |
195 | ... | |
196 | </pre></div> | |
197 | ||
198 | <P> | |
199 | The <tt class="keyword">try</tt> statement works as follows. | |
200 | ||
201 | <P> | |
202 | ||
203 | <UL> | |
204 | <LI>First, the <em>try clause</em> (the statement(s) between the | |
205 | <tt class="keyword">try</tt> and <tt class="keyword">except</tt> keywords) is executed. | |
206 | ||
207 | <P> | |
208 | </LI> | |
209 | <LI>If no exception occurs, the <em>except clause</em> is skipped and | |
210 | execution of the <tt class="keyword">try</tt> statement is finished. | |
211 | ||
212 | <P> | |
213 | </LI> | |
214 | <LI>If an exception occurs during execution of the try clause, the rest of | |
215 | the clause is skipped. Then if its type matches the exception named | |
216 | after the <tt class="keyword">except</tt> keyword, the except clause is executed, and | |
217 | then execution continues after the <tt class="keyword">try</tt> statement. | |
218 | ||
219 | <P> | |
220 | </LI> | |
221 | <LI>If an exception occurs which does not match the exception named in the | |
222 | except clause, it is passed on to outer <tt class="keyword">try</tt> statements; if | |
223 | no handler is found, it is an <em>unhandled exception</em> and execution | |
224 | stops with a message as shown above. | |
225 | ||
226 | <P> | |
227 | </LI> | |
228 | </UL> | |
229 | ||
230 | <P> | |
231 | A <tt class="keyword">try</tt> statement may have more than one except clause, to | |
232 | specify handlers for different exceptions. At most one handler will | |
233 | be executed. Handlers only handle exceptions that occur in the | |
234 | corresponding try clause, not in other handlers of the same | |
235 | <tt class="keyword">try</tt> statement. An except clause may name multiple exceptions | |
236 | as a parenthesized tuple, for example: | |
237 | ||
238 | <P> | |
239 | <div class="verbatim"><pre> | |
240 | ... except (RuntimeError, TypeError, NameError): | |
241 | ... pass | |
242 | </pre></div> | |
243 | ||
244 | <P> | |
245 | The last except clause may omit the exception name(s), to serve as a | |
246 | wildcard. Use this with extreme caution, since it is easy to mask a | |
247 | real programming error in this way! It can also be used to print an | |
248 | error message and then re-raise the exception (allowing a caller to | |
249 | handle the exception as well): | |
250 | ||
251 | <P> | |
252 | <div class="verbatim"><pre> | |
253 | import sys | |
254 | ||
255 | try: | |
256 | f = open('myfile.txt') | |
257 | s = f.readline() | |
258 | i = int(s.strip()) | |
259 | except IOError, (errno, strerror): | |
260 | print "I/O error(%s): %s" % (errno, strerror) | |
261 | except ValueError: | |
262 | print "Could not convert data to an integer." | |
263 | except: | |
264 | print "Unexpected error:", sys.exc_info()[0] | |
265 | raise | |
266 | </pre></div> | |
267 | ||
268 | <P> | |
269 | The <tt class="keyword">try</tt> ... <tt class="keyword">except</tt> statement has an optional | |
270 | <em>else clause</em>, which, when present, must follow all except | |
271 | clauses. It is useful for code that must be executed if the try | |
272 | clause does not raise an exception. For example: | |
273 | ||
274 | <P> | |
275 | <div class="verbatim"><pre> | |
276 | for arg in sys.argv[1:]: | |
277 | try: | |
278 | f = open(arg, 'r') | |
279 | except IOError: | |
280 | print 'cannot open', arg | |
281 | else: | |
282 | print arg, 'has', len(f.readlines()), 'lines' | |
283 | f.close() | |
284 | </pre></div> | |
285 | ||
286 | <P> | |
287 | The use of the <tt class="keyword">else</tt> clause is better than adding additional | |
288 | code to the <tt class="keyword">try</tt> clause because it avoids accidentally | |
289 | catching an exception that wasn't raised by the code being protected | |
290 | by the <tt class="keyword">try</tt> ... <tt class="keyword">except</tt> statement. | |
291 | ||
292 | <P> | |
293 | When an exception occurs, it may have an associated value, also known as | |
294 | the exception's <em>argument</em>. | |
295 | The presence and type of the argument depend on the exception type. | |
296 | ||
297 | <P> | |
298 | The except clause may specify a variable after the exception name (or tuple). | |
299 | The variable is bound to an exception instance with the arguments stored | |
300 | in <code>instance.args</code>. For convenience, the exception instance | |
301 | defines <tt class="method">__getitem__</tt> and <tt class="method">__str__</tt> so the arguments can | |
302 | be accessed or printed directly without having to reference <code>.args</code>. | |
303 | ||
304 | <P> | |
305 | <div class="verbatim"><pre> | |
306 | >>> try: | |
307 | ... raise Exception('spam', 'eggs') | |
308 | ... except Exception, inst: | |
309 | ... print type(inst) # the exception instance | |
310 | ... print inst.args # arguments stored in .args | |
311 | ... print inst # __str__ allows args to printed directly | |
312 | ... x, y = inst # __getitem__ allows args to be unpacked directly | |
313 | ... print 'x =', x | |
314 | ... print 'y =', y | |
315 | ... | |
316 | <type 'instance'> | |
317 | ('spam', 'eggs') | |
318 | ('spam', 'eggs') | |
319 | x = spam | |
320 | y = eggs | |
321 | </pre></div> | |
322 | ||
323 | <P> | |
324 | If an exception has an argument, it is printed as the last part | |
325 | (`detail') of the message for unhandled exceptions. | |
326 | ||
327 | <P> | |
328 | Exception handlers don't just handle exceptions if they occur | |
329 | immediately in the try clause, but also if they occur inside functions | |
330 | that are called (even indirectly) in the try clause. | |
331 | For example: | |
332 | ||
333 | <P> | |
334 | <div class="verbatim"><pre> | |
335 | >>> def this_fails(): | |
336 | ... x = 1/0 | |
337 | ... | |
338 | >>> try: | |
339 | ... this_fails() | |
340 | ... except ZeroDivisionError, detail: | |
341 | ... print 'Handling run-time error:', detail | |
342 | ... | |
343 | Handling run-time error: integer division or modulo by zero | |
344 | </pre></div> | |
345 | ||
346 | <P> | |
347 | ||
348 | <H1><A NAME="SECTION0010400000000000000000"></A><A NAME="raising"></A> | |
349 | <BR> | |
350 | 8.4 Raising Exceptions | |
351 | </H1> | |
352 | ||
353 | <P> | |
354 | The <tt class="keyword">raise</tt> statement allows the programmer to force a | |
355 | specified exception to occur. | |
356 | For example: | |
357 | ||
358 | <P> | |
359 | <div class="verbatim"><pre> | |
360 | >>> raise NameError, 'HiThere' | |
361 | Traceback (most recent call last): | |
362 | File "<stdin>", line 1, in ? | |
363 | NameError: HiThere | |
364 | </pre></div> | |
365 | ||
366 | <P> | |
367 | The first argument to <tt class="keyword">raise</tt> names the exception to be | |
368 | raised. The optional second argument specifies the exception's | |
369 | argument. Alternatively, the above could be written as | |
370 | <code>raise NameError('HiThere')</code>. Either form works fine, but there | |
371 | seems to be a growing stylistic preference for the latter. | |
372 | ||
373 | <P> | |
374 | If you need to determine whether an exception was raised but don't | |
375 | intend to handle it, a simpler form of the <tt class="keyword">raise</tt> statement | |
376 | allows you to re-raise the exception: | |
377 | ||
378 | <P> | |
379 | <div class="verbatim"><pre> | |
380 | >>> try: | |
381 | ... raise NameError, 'HiThere' | |
382 | ... except NameError: | |
383 | ... print 'An exception flew by!' | |
384 | ... raise | |
385 | ... | |
386 | An exception flew by! | |
387 | Traceback (most recent call last): | |
388 | File "<stdin>", line 2, in ? | |
389 | NameError: HiThere | |
390 | </pre></div> | |
391 | ||
392 | <P> | |
393 | ||
394 | <H1><A NAME="SECTION0010500000000000000000"></A><A NAME="userExceptions"></A> | |
395 | <BR> | |
396 | 8.5 User-defined Exceptions | |
397 | </H1> | |
398 | ||
399 | <P> | |
400 | Programs may name their own exceptions by creating a new exception | |
401 | class. Exceptions should typically be derived from the | |
402 | <tt class="exception">Exception</tt> class, either directly or indirectly. For | |
403 | example: | |
404 | ||
405 | <P> | |
406 | <div class="verbatim"><pre> | |
407 | >>> class MyError(Exception): | |
408 | ... def __init__(self, value): | |
409 | ... self.value = value | |
410 | ... def __str__(self): | |
411 | ... return repr(self.value) | |
412 | ... | |
413 | >>> try: | |
414 | ... raise MyError(2*2) | |
415 | ... except MyError, e: | |
416 | ... print 'My exception occurred, value:', e.value | |
417 | ... | |
418 | My exception occurred, value: 4 | |
419 | >>> raise MyError, 'oops!' | |
420 | Traceback (most recent call last): | |
421 | File "<stdin>", line 1, in ? | |
422 | __main__.MyError: 'oops!' | |
423 | </pre></div> | |
424 | ||
425 | <P> | |
426 | In this example, the default <tt class="method">__init__</tt> of <tt class="class">Exception</tt> | |
427 | has been overridden. The new behavior simply creates the <var>value</var> | |
428 | attribute. This replaces the default behavior of creating the | |
429 | <var>args</var> attribute. | |
430 | ||
431 | <P> | |
432 | Exception classes can be defined which do anything any other class can | |
433 | do, but are usually kept simple, often only offering a number of | |
434 | attributes that allow information about the error to be extracted by | |
435 | handlers for the exception. When creating a module that can raise | |
436 | several distinct errors, a common practice is to create a base class | |
437 | for exceptions defined by that module, and subclass that to create | |
438 | specific exception classes for different error conditions: | |
439 | ||
440 | <P> | |
441 | <div class="verbatim"><pre> | |
442 | class Error(Exception): | |
443 | """Base class for exceptions in this module.""" | |
444 | pass | |
445 | ||
446 | class InputError(Error): | |
447 | """Exception raised for errors in the input. | |
448 | ||
449 | Attributes: | |
450 | expression -- input expression in which the error occurred | |
451 | message -- explanation of the error | |
452 | """ | |
453 | ||
454 | def __init__(self, expression, message): | |
455 | self.expression = expression | |
456 | self.message = message | |
457 | ||
458 | class TransitionError(Error): | |
459 | """Raised when an operation attempts a state transition that's not | |
460 | allowed. | |
461 | ||
462 | Attributes: | |
463 | previous -- state at beginning of transition | |
464 | next -- attempted new state | |
465 | message -- explanation of why the specific transition is not allowed | |
466 | """ | |
467 | ||
468 | def __init__(self, previous, next, message): | |
469 | self.previous = previous | |
470 | self.next = next | |
471 | self.message = message | |
472 | </pre></div> | |
473 | ||
474 | <P> | |
475 | Most exceptions are defined with names that end in ``Error,'' similar | |
476 | to the naming of the standard exceptions. | |
477 | ||
478 | <P> | |
479 | Many standard modules define their own exceptions to report errors | |
480 | that may occur in functions they define. More information on classes | |
481 | is presented in chapter <A HREF="node11.html#classes">9</A>, ``Classes.'' | |
482 | ||
483 | <P> | |
484 | ||
485 | <H1><A NAME="SECTION0010600000000000000000"></A><A NAME="cleanup"></A> | |
486 | <BR> | |
487 | 8.6 Defining Clean-up Actions | |
488 | </H1> | |
489 | ||
490 | <P> | |
491 | The <tt class="keyword">try</tt> statement has another optional clause which is | |
492 | intended to define clean-up actions that must be executed under all | |
493 | circumstances. For example: | |
494 | ||
495 | <P> | |
496 | <div class="verbatim"><pre> | |
497 | >>> try: | |
498 | ... raise KeyboardInterrupt | |
499 | ... finally: | |
500 | ... print 'Goodbye, world!' | |
501 | ... | |
502 | Goodbye, world! | |
503 | Traceback (most recent call last): | |
504 | File "<stdin>", line 2, in ? | |
505 | KeyboardInterrupt | |
506 | </pre></div> | |
507 | ||
508 | <P> | |
509 | A <em>finally clause</em> is executed whether or not an exception has | |
510 | occurred in the try clause. When an exception has occurred, it is | |
511 | re-raised after the finally clause is executed. The finally clause is | |
512 | also executed ``on the way out'' when the <tt class="keyword">try</tt> statement is | |
513 | left via a <tt class="keyword">break</tt> or <tt class="keyword">return</tt> statement. | |
514 | ||
515 | <P> | |
516 | The code in the finally clause is useful for releasing external | |
517 | resources (such as files or network connections), regardless of | |
518 | whether the use of the resource was successful. | |
519 | ||
520 | <P> | |
521 | A <tt class="keyword">try</tt> statement must either have one or more except clauses | |
522 | or one finally clause, but not both (because it would be unclear which | |
523 | clause should be executed first). | |
524 | ||
525 | <P> | |
526 | ||
527 | <DIV CLASS="navigation"> | |
528 | <div class='online-navigation'> | |
529 | <p></p><hr /> | |
530 | <table align="center" width="100%" cellpadding="0" cellspacing="2"> | |
531 | <tr> | |
532 | <td class='online-navigation'><a rel="prev" title="7. Input and Output" | |
533 | href="node9.html"><img src='../icons/previous.png' | |
534 | border='0' height='32' alt='Previous Page' width='32' /></A></td> | |
535 | <td class='online-navigation'><a rel="parent" title="Python Tutorial" | |
536 | href="tut.html"><img src='../icons/up.png' | |
537 | border='0' height='32' alt='Up One Level' width='32' /></A></td> | |
538 | <td class='online-navigation'><a rel="next" title="9. Classes" | |
539 | href="node11.html"><img src='../icons/next.png' | |
540 | border='0' height='32' alt='Next Page' width='32' /></A></td> | |
541 | <td align="center" width="100%">Python Tutorial</td> | |
542 | <td class='online-navigation'><a rel="contents" title="Table of Contents" | |
543 | href="node2.html"><img src='../icons/contents.png' | |
544 | border='0' height='32' alt='Contents' width='32' /></A></td> | |
545 | <td class='online-navigation'><img src='../icons/blank.png' | |
546 | border='0' height='32' alt='' width='32' /></td> | |
547 | <td class='online-navigation'><a rel="index" title="Index" | |
548 | href="node19.html"><img src='../icons/index.png' | |
549 | border='0' height='32' alt='Index' width='32' /></A></td> | |
550 | </tr></table> | |
551 | <div class='online-navigation'> | |
552 | <b class="navlabel">Previous:</b> | |
553 | <a class="sectref" rel="prev" href="node9.html">7. Input and Output</A> | |
554 | <b class="navlabel">Up:</b> | |
555 | <a class="sectref" rel="parent" href="tut.html">Python Tutorial</A> | |
556 | <b class="navlabel">Next:</b> | |
557 | <a class="sectref" rel="next" href="node11.html">9. Classes</A> | |
558 | </div> | |
559 | </div> | |
560 | <hr /> | |
561 | <span class="release-info">Release 2.4.2, documentation updated on 28 September 2005.</span> | |
562 | </DIV> | |
563 | <!--End of Navigation Panel--> | |
564 | <ADDRESS> | |
565 | See <i><a href="about.html">About this document...</a></i> for information on suggesting changes. | |
566 | </ADDRESS> | |
567 | </BODY> | |
568 | </HTML> |