| 
									
										
										
										
											2008-08-08 06:50:56 +00:00
										 |  |  | .. _tut-errors:
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | *********************
 | 
					
						
							|  |  |  | Errors and Exceptions
 | 
					
						
							|  |  |  | *********************
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Until now error messages haven't been more than mentioned, but if you have tried
 | 
					
						
							|  |  |  | out the examples you have probably seen some.  There are (at least) two
 | 
					
						
							|  |  |  | distinguishable kinds of errors: *syntax errors* and *exceptions*.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .. _tut-syntaxerrors:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Syntax Errors
 | 
					
						
							|  |  |  | =============
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Syntax errors, also known as parsing errors, are perhaps the most common kind of
 | 
					
						
							|  |  |  | complaint you get while you are still learning Python::
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-31 03:25:11 +00:00
										 |  |  |    >>> while True print('Hello world')
 | 
					
						
							| 
									
										
										
										
											2016-09-30 15:38:48 -04:00
										 |  |  |      File "<stdin>", line 1
 | 
					
						
							| 
									
										
										
										
											2007-08-31 03:25:11 +00:00
										 |  |  |        while True print('Hello world')
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  |                       ^
 | 
					
						
							|  |  |  |    SyntaxError: invalid syntax
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The parser repeats the offending line and displays a little 'arrow' pointing at
 | 
					
						
							|  |  |  | the earliest point in the line where the error was detected.  The error is
 | 
					
						
							|  |  |  | caused by (or at least detected at) the token *preceding* the arrow: in the
 | 
					
						
							| 
									
										
										
										
											2007-09-04 07:15:32 +00:00
										 |  |  | example, the error is detected at the function :func:`print`, since a colon
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  | (``':'``) is missing before it.  File name and line number are printed so you
 | 
					
						
							|  |  |  | know where to look in case the input came from a script.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .. _tut-exceptions:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Exceptions
 | 
					
						
							|  |  |  | ==========
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Even if a statement or expression is syntactically correct, it may cause an
 | 
					
						
							|  |  |  | error when an attempt is made to execute it. Errors detected during execution
 | 
					
						
							|  |  |  | are called *exceptions* and are not unconditionally fatal: you will soon learn
 | 
					
						
							|  |  |  | how to handle them in Python programs.  Most exceptions are not handled by
 | 
					
						
							|  |  |  | programs, however, and result in error messages as shown here::
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    >>> 10 * (1/0)
 | 
					
						
							|  |  |  |    Traceback (most recent call last):
 | 
					
						
							| 
									
										
										
										
											2016-09-30 15:38:48 -04:00
										 |  |  |      File "<stdin>", line 1, in <module>
 | 
					
						
							| 
									
										
										
										
											2013-10-06 09:11:14 +02:00
										 |  |  |    ZeroDivisionError: division by zero
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  |    >>> 4 + spam*3
 | 
					
						
							|  |  |  |    Traceback (most recent call last):
 | 
					
						
							| 
									
										
										
										
											2016-09-30 15:38:48 -04:00
										 |  |  |      File "<stdin>", line 1, in <module>
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  |    NameError: name 'spam' is not defined
 | 
					
						
							|  |  |  |    >>> '2' + 2
 | 
					
						
							|  |  |  |    Traceback (most recent call last):
 | 
					
						
							| 
									
										
										
										
											2016-09-30 15:38:48 -04:00
										 |  |  |      File "<stdin>", line 1, in <module>
 | 
					
						
							| 
									
										
										
										
											2021-08-21 13:59:18 -05:00
										 |  |  |    TypeError: can only concatenate str (not "int") to str
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | The last line of the error message indicates what happened. Exceptions come in
 | 
					
						
							|  |  |  | different types, and the type is printed as part of the message: the types in
 | 
					
						
							|  |  |  | the example are :exc:`ZeroDivisionError`, :exc:`NameError` and :exc:`TypeError`.
 | 
					
						
							|  |  |  | The string printed as the exception type is the name of the built-in exception
 | 
					
						
							|  |  |  | that occurred.  This is true for all built-in exceptions, but need not be true
 | 
					
						
							|  |  |  | for user-defined exceptions (although it is a useful convention). Standard
 | 
					
						
							|  |  |  | exception names are built-in identifiers (not reserved keywords).
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The rest of the line provides detail based on the type of exception and what
 | 
					
						
							|  |  |  | caused it.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The preceding part of the error message shows the context where the exception
 | 
					
						
							| 
									
										
										
										
											2020-05-01 06:30:10 +02:00
										 |  |  | occurred, in the form of a stack traceback. In general it contains a stack
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  | traceback listing source lines; however, it will not display lines read from
 | 
					
						
							|  |  |  | standard input.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :ref:`bltin-exceptions` lists the built-in exceptions and their meanings.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .. _tut-handling:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Handling Exceptions
 | 
					
						
							|  |  |  | ===================
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | It is possible to write programs that handle selected exceptions. Look at the
 | 
					
						
							|  |  |  | following example, which asks the user for input until a valid integer has been
 | 
					
						
							|  |  |  | entered, but allows the user to interrupt the program (using :kbd:`Control-C` or
 | 
					
						
							|  |  |  | whatever the operating system supports); note that a user-generated interruption
 | 
					
						
							|  |  |  | is signalled by raising the :exc:`KeyboardInterrupt` exception. ::
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    >>> while True:
 | 
					
						
							|  |  |  |    ...     try:
 | 
					
						
							| 
									
										
										
										
											2007-08-17 05:54:09 +00:00
										 |  |  |    ...         x = int(input("Please enter a number: "))
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  |    ...         break
 | 
					
						
							|  |  |  |    ...     except ValueError:
 | 
					
						
							| 
									
										
										
										
											2007-08-31 03:25:11 +00:00
										 |  |  |    ...         print("Oops!  That was no valid number.  Try again...")
 | 
					
						
							| 
									
										
										
										
											2009-01-03 21:18:54 +00:00
										 |  |  |    ...
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | The :keyword:`try` statement works as follows.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | * First, the *try clause* (the statement(s) between the :keyword:`try` and
 | 
					
						
							|  |  |  |   :keyword:`except` keywords) is executed.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | * If no exception occurs, the *except clause* is skipped and execution of the
 | 
					
						
							|  |  |  |   :keyword:`try` statement is finished.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 03:07:11 -03:00
										 |  |  | * If an exception occurs during execution of the :keyword:`try` clause, the rest of the
 | 
					
						
							|  |  |  |   clause is skipped.  Then, if its type matches the exception named after the
 | 
					
						
							|  |  |  |   :keyword:`except` keyword, the *except clause* is executed, and then execution
 | 
					
						
							|  |  |  |   continues after the try/except block.
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 03:07:11 -03:00
										 |  |  | * If an exception occurs which does not match the exception named in the *except
 | 
					
						
							|  |  |  |   clause*, it is passed on to outer :keyword:`try` statements; if no handler is
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  |   found, it is an *unhandled exception* and execution stops with a message as
 | 
					
						
							|  |  |  |   shown above.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 03:07:11 -03:00
										 |  |  | A :keyword:`try` statement may have more than one *except clause*, to specify
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  | handlers for different exceptions.  At most one handler will be executed.
 | 
					
						
							| 
									
										
										
										
											2021-01-31 03:07:11 -03:00
										 |  |  | Handlers only handle exceptions that occur in the corresponding *try clause*,
 | 
					
						
							|  |  |  | not in other handlers of the same :keyword:`!try` statement.  An *except clause*
 | 
					
						
							|  |  |  | may name multiple exceptions as a parenthesized tuple, for example::
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-27 21:28:21 +00:00
										 |  |  |    ... except (RuntimeError, TypeError, NameError):
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  |    ...     pass
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-06 21:15:01 +03:00
										 |  |  | A class in an :keyword:`except` clause is compatible with an exception if it is
 | 
					
						
							|  |  |  | the same class or a base class thereof (but not the other way around --- an
 | 
					
						
							| 
									
										
										
										
											2021-01-31 03:07:11 -03:00
										 |  |  | *except clause* listing a derived class is not compatible with a base class).
 | 
					
						
							|  |  |  | For example, the following code will print B, C, D in that order::
 | 
					
						
							| 
									
										
										
										
											2016-11-06 21:15:01 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |    class B(Exception):
 | 
					
						
							|  |  |  |        pass
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    class C(B):
 | 
					
						
							|  |  |  |        pass
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    class D(C):
 | 
					
						
							|  |  |  |        pass
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    for cls in [B, C, D]:
 | 
					
						
							|  |  |  |        try:
 | 
					
						
							|  |  |  |            raise cls()
 | 
					
						
							|  |  |  |        except D:
 | 
					
						
							|  |  |  |            print("D")
 | 
					
						
							|  |  |  |        except C:
 | 
					
						
							|  |  |  |            print("C")
 | 
					
						
							|  |  |  |        except B:
 | 
					
						
							|  |  |  |            print("B")
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-31 03:07:11 -03:00
										 |  |  | Note that if the *except clauses* were reversed (with ``except B`` first), it
 | 
					
						
							|  |  |  | would have printed B, B, B --- the first matching *except clause* is triggered.
 | 
					
						
							| 
									
										
										
										
											2016-11-06 21:15:01 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-13 21:45:33 +01:00
										 |  |  | When an exception occurs, it may have associated values, also known as the
 | 
					
						
							|  |  |  | exception's *arguments*. The presence and types of the arguments depend on the
 | 
					
						
							|  |  |  | exception type.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The *except clause* may specify a variable after the exception name.  The
 | 
					
						
							|  |  |  | variable is bound to the exception instance which typically has an ``args``
 | 
					
						
							|  |  |  | attribute that stores the arguments. For convenience, builtin exception
 | 
					
						
							| 
									
										
										
										
											2023-07-29 08:48:10 +03:00
										 |  |  | types define :meth:`~object.__str__` to print all the arguments without explicitly
 | 
					
						
							| 
									
										
										
										
											2022-04-13 21:45:33 +01:00
										 |  |  | accessing ``.args``.  ::
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    >>> try:
 | 
					
						
							|  |  |  |    ...     raise Exception('spam', 'eggs')
 | 
					
						
							|  |  |  |    ... except Exception as inst:
 | 
					
						
							| 
									
										
										
										
											2023-03-22 19:43:41 +01:00
										 |  |  |    ...     print(type(inst))    # the exception type
 | 
					
						
							| 
									
										
										
										
											2022-04-13 21:45:33 +01:00
										 |  |  |    ...     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 = spam
 | 
					
						
							|  |  |  |    y = eggs
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-29 08:48:10 +03:00
										 |  |  | The exception's :meth:`~object.__str__` output is printed as the last part ('detail')
 | 
					
						
							| 
									
										
										
										
											2022-04-13 21:45:33 +01:00
										 |  |  | of the message for unhandled exceptions.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :exc:`BaseException` is the common base class of all exceptions. One of its
 | 
					
						
							|  |  |  | subclasses, :exc:`Exception`, is the base class of all the non-fatal exceptions.
 | 
					
						
							|  |  |  | Exceptions which are not subclasses of :exc:`Exception` are not typically
 | 
					
						
							|  |  |  | handled, because they are used to indicate that the program should terminate.
 | 
					
						
							|  |  |  | They include :exc:`SystemExit` which is raised by :meth:`sys.exit` and
 | 
					
						
							|  |  |  | :exc:`KeyboardInterrupt` which is raised when a user wishes to interrupt
 | 
					
						
							|  |  |  | the program.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :exc:`Exception` can be used as a wildcard that catches (almost) everything.
 | 
					
						
							|  |  |  | However, it is good practice to be as specific as possible with the types
 | 
					
						
							|  |  |  | of exceptions that we intend to handle, and to allow any unexpected
 | 
					
						
							|  |  |  | exceptions to propagate on.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The most common pattern for handling :exc:`Exception` is to print or log
 | 
					
						
							|  |  |  | the exception and then re-raise it (allowing a caller to handle the
 | 
					
						
							|  |  |  | exception as well)::
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |    import sys
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    try:
 | 
					
						
							|  |  |  |        f = open('myfile.txt')
 | 
					
						
							|  |  |  |        s = f.readline()
 | 
					
						
							|  |  |  |        i = int(s.strip())
 | 
					
						
							| 
									
										
										
										
											2014-04-01 01:13:30 +03:00
										 |  |  |    except OSError as err:
 | 
					
						
							| 
									
										
										
										
											2022-04-13 21:45:33 +01:00
										 |  |  |        print("OS error:", err)
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  |    except ValueError:
 | 
					
						
							| 
									
										
										
										
											2007-08-31 03:25:11 +00:00
										 |  |  |        print("Could not convert data to an integer.")
 | 
					
						
							| 
									
										
										
										
											2022-04-13 21:45:33 +01:00
										 |  |  |    except Exception as err:
 | 
					
						
							| 
									
										
										
										
											2021-08-06 21:44:15 +01:00
										 |  |  |        print(f"Unexpected {err=}, {type(err)=}")
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  |        raise
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The :keyword:`try` ... :keyword:`except` statement has an optional *else
 | 
					
						
							| 
									
										
										
										
											2021-01-31 03:07:11 -03:00
										 |  |  | clause*, which, when present, must follow all *except clauses*.  It is useful
 | 
					
						
							|  |  |  | for code that must be executed if the *try clause* does not raise an exception.
 | 
					
						
							|  |  |  | For example::
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |    for arg in sys.argv[1:]:
 | 
					
						
							|  |  |  |        try:
 | 
					
						
							|  |  |  |            f = open(arg, 'r')
 | 
					
						
							| 
									
										
										
										
											2016-11-16 21:13:43 +05:30
										 |  |  |        except OSError:
 | 
					
						
							| 
									
										
										
										
											2007-08-31 03:25:11 +00:00
										 |  |  |            print('cannot open', arg)
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  |        else:
 | 
					
						
							| 
									
										
										
										
											2007-08-31 03:25:11 +00:00
										 |  |  |            print(arg, 'has', len(f.readlines()), 'lines')
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  |            f.close()
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-19 08:09:46 +02:00
										 |  |  | The use of the :keyword:`!else` clause is better than adding additional code to
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  | the :keyword:`try` clause because it avoids accidentally catching an exception
 | 
					
						
							| 
									
										
										
										
											2018-12-19 08:09:46 +02:00
										 |  |  | that wasn't raised by the code being protected by the :keyword:`!try` ...
 | 
					
						
							|  |  |  | :keyword:`!except` statement.
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-13 21:45:33 +01:00
										 |  |  | Exception handlers do not handle only exceptions that occur immediately in the
 | 
					
						
							|  |  |  | *try clause*, but also those that occur inside functions that are called (even
 | 
					
						
							| 
									
										
										
										
											2021-01-31 03:07:11 -03:00
										 |  |  | indirectly) in the *try clause*. For example::
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |    >>> def this_fails():
 | 
					
						
							|  |  |  |    ...     x = 1/0
 | 
					
						
							| 
									
										
										
										
											2009-01-03 21:18:54 +00:00
										 |  |  |    ...
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  |    >>> try:
 | 
					
						
							|  |  |  |    ...     this_fails()
 | 
					
						
							| 
									
										
										
										
											2008-08-08 06:50:56 +00:00
										 |  |  |    ... except ZeroDivisionError as err:
 | 
					
						
							|  |  |  |    ...     print('Handling run-time error:', err)
 | 
					
						
							| 
									
										
										
										
											2009-01-03 21:18:54 +00:00
										 |  |  |    ...
 | 
					
						
							| 
									
										
										
										
											2016-09-28 22:48:57 +03:00
										 |  |  |    Handling run-time error: division by zero
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .. _tut-raising:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Raising Exceptions
 | 
					
						
							|  |  |  | ==================
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The :keyword:`raise` statement allows the programmer to force a specified
 | 
					
						
							|  |  |  | exception to occur. For example::
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-10 00:31:50 +00:00
										 |  |  |    >>> raise NameError('HiThere')
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  |    Traceback (most recent call last):
 | 
					
						
							| 
									
										
										
										
											2016-09-30 15:38:48 -04:00
										 |  |  |      File "<stdin>", line 1, in <module>
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  |    NameError: HiThere
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-10 00:36:57 +00:00
										 |  |  | The sole argument to :keyword:`raise` indicates the exception to be raised.
 | 
					
						
							|  |  |  | This must be either an exception instance or an exception class (a class that
 | 
					
						
							| 
									
										
										
										
											2022-04-13 21:45:33 +01:00
										 |  |  | derives from :class:`BaseException`, such as :exc:`Exception` or one of its
 | 
					
						
							|  |  |  | subclasses).  If an exception class is passed, it will be implicitly
 | 
					
						
							|  |  |  | instantiated by calling its constructor with no arguments::
 | 
					
						
							| 
									
										
										
										
											2016-11-06 21:15:01 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |    raise ValueError  # shorthand for 'raise ValueError()'
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | If you need to determine whether an exception was raised but don't intend to
 | 
					
						
							|  |  |  | handle it, a simpler form of the :keyword:`raise` statement allows you to
 | 
					
						
							|  |  |  | re-raise the exception::
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    >>> try:
 | 
					
						
							| 
									
										
										
										
											2007-09-10 00:31:50 +00:00
										 |  |  |    ...     raise NameError('HiThere')
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  |    ... except NameError:
 | 
					
						
							| 
									
										
										
										
											2007-08-31 03:25:11 +00:00
										 |  |  |    ...     print('An exception flew by!')
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  |    ...     raise
 | 
					
						
							|  |  |  |    ...
 | 
					
						
							|  |  |  |    An exception flew by!
 | 
					
						
							|  |  |  |    Traceback (most recent call last):
 | 
					
						
							| 
									
										
										
										
											2016-09-30 15:38:48 -04:00
										 |  |  |      File "<stdin>", line 2, in <module>
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  |    NameError: HiThere
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 14:11:32 -07:00
										 |  |  | .. _tut-exception-chaining:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Exception Chaining
 | 
					
						
							|  |  |  | ==================
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-05 02:36:04 +02:00
										 |  |  | If an unhandled exception occurs inside an :keyword:`except` section, it will
 | 
					
						
							|  |  |  | have the exception being handled attached to it and included in the error
 | 
					
						
							|  |  |  | message::
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     >>> try:
 | 
					
						
							|  |  |  |     ...     open("database.sqlite")
 | 
					
						
							|  |  |  |     ... except OSError:
 | 
					
						
							|  |  |  |     ...     raise RuntimeError("unable to handle error")
 | 
					
						
							|  |  |  |     ...
 | 
					
						
							|  |  |  |     Traceback (most recent call last):
 | 
					
						
							|  |  |  |       File "<stdin>", line 2, in <module>
 | 
					
						
							|  |  |  |     FileNotFoundError: [Errno 2] No such file or directory: 'database.sqlite'
 | 
					
						
							|  |  |  |     <BLANKLINE>
 | 
					
						
							|  |  |  |     During handling of the above exception, another exception occurred:
 | 
					
						
							|  |  |  |     <BLANKLINE>
 | 
					
						
							|  |  |  |     Traceback (most recent call last):
 | 
					
						
							|  |  |  |       File "<stdin>", line 4, in <module>
 | 
					
						
							|  |  |  |     RuntimeError: unable to handle error
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | To indicate that an exception is a direct consequence of another, the
 | 
					
						
							|  |  |  | :keyword:`raise` statement allows an optional :keyword:`from<raise>` clause::
 | 
					
						
							| 
									
										
										
										
											2019-08-14 14:11:32 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 11:45:01 +09:00
										 |  |  |     # exc must be exception instance or None.
 | 
					
						
							|  |  |  |     raise RuntimeError from exc
 | 
					
						
							| 
									
										
										
										
											2019-08-14 14:11:32 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | This can be useful when you are transforming exceptions. For example::
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     >>> def func():
 | 
					
						
							| 
									
										
										
										
											2020-12-15 18:47:26 -08:00
										 |  |  |     ...     raise ConnectionError
 | 
					
						
							| 
									
										
										
										
											2019-08-14 14:11:32 -07:00
										 |  |  |     ...
 | 
					
						
							|  |  |  |     >>> try:
 | 
					
						
							|  |  |  |     ...     func()
 | 
					
						
							| 
									
										
										
										
											2020-12-15 18:47:26 -08:00
										 |  |  |     ... except ConnectionError as exc:
 | 
					
						
							| 
									
										
										
										
											2019-08-14 14:11:32 -07:00
										 |  |  |     ...     raise RuntimeError('Failed to open database') from exc
 | 
					
						
							|  |  |  |     ...
 | 
					
						
							|  |  |  |     Traceback (most recent call last):
 | 
					
						
							|  |  |  |       File "<stdin>", line 2, in <module>
 | 
					
						
							|  |  |  |       File "<stdin>", line 2, in func
 | 
					
						
							| 
									
										
										
										
											2020-12-15 18:47:26 -08:00
										 |  |  |     ConnectionError
 | 
					
						
							| 
									
										
										
										
											2019-08-14 14:11:32 -07:00
										 |  |  |     <BLANKLINE>
 | 
					
						
							|  |  |  |     The above exception was the direct cause of the following exception:
 | 
					
						
							|  |  |  |     <BLANKLINE>
 | 
					
						
							|  |  |  |     Traceback (most recent call last):
 | 
					
						
							|  |  |  |       File "<stdin>", line 4, in <module>
 | 
					
						
							| 
									
										
										
										
											2020-11-06 11:45:01 +09:00
										 |  |  |     RuntimeError: Failed to open database
 | 
					
						
							| 
									
										
										
										
											2019-08-14 14:11:32 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-05 02:36:04 +02:00
										 |  |  | It also allows disabling automatic exception chaining using the ``from None``
 | 
					
						
							|  |  |  | idiom::
 | 
					
						
							| 
									
										
										
										
											2019-08-14 14:11:32 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     >>> try:
 | 
					
						
							|  |  |  |     ...     open('database.sqlite')
 | 
					
						
							| 
									
										
										
										
											2021-05-21 13:54:01 -04:00
										 |  |  |     ... except OSError:
 | 
					
						
							| 
									
										
										
										
											2019-08-14 14:11:32 -07:00
										 |  |  |     ...     raise RuntimeError from None
 | 
					
						
							|  |  |  |     ...
 | 
					
						
							|  |  |  |     Traceback (most recent call last):
 | 
					
						
							|  |  |  |       File "<stdin>", line 4, in <module>
 | 
					
						
							|  |  |  |     RuntimeError
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 11:45:01 +09:00
										 |  |  | For more information about chaining mechanics, see :ref:`bltin-exceptions`.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 14:11:32 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  | .. _tut-userexceptions:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | User-defined Exceptions
 | 
					
						
							|  |  |  | =======================
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-16 16:00:31 +00:00
										 |  |  | Programs may name their own exceptions by creating a new exception class (see
 | 
					
						
							|  |  |  | :ref:`tut-classes` for more about Python classes).  Exceptions should typically
 | 
					
						
							| 
									
										
										
										
											2016-08-12 09:43:59 -07:00
										 |  |  | be derived from the :exc:`Exception` class, either directly or indirectly.
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Exception classes can be defined which do anything any other class can do, but
 | 
					
						
							|  |  |  | are usually kept simple, often only offering a number of attributes that allow
 | 
					
						
							| 
									
										
										
										
											2022-01-04 00:52:09 +02:00
										 |  |  | information about the error to be extracted by handlers for the exception.
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-03 08:05:59 -07:00
										 |  |  | Most exceptions are defined with names that end in "Error", similar to the
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  | naming of the standard exceptions.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Many standard modules define their own exceptions to report errors that may
 | 
					
						
							| 
									
										
										
										
											2022-04-13 21:45:33 +01:00
										 |  |  | occur in functions they define.
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .. _tut-cleanup:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Defining Clean-up Actions
 | 
					
						
							|  |  |  | =========================
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The :keyword:`try` statement has another optional clause which is intended to
 | 
					
						
							|  |  |  | define clean-up actions that must be executed under all circumstances.  For
 | 
					
						
							|  |  |  | example::
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    >>> try:
 | 
					
						
							|  |  |  |    ...     raise KeyboardInterrupt
 | 
					
						
							|  |  |  |    ... finally:
 | 
					
						
							| 
									
										
										
										
											2007-08-31 03:25:11 +00:00
										 |  |  |    ...     print('Goodbye, world!')
 | 
					
						
							| 
									
										
										
										
											2009-01-03 21:18:54 +00:00
										 |  |  |    ...
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  |    Goodbye, world!
 | 
					
						
							|  |  |  |    Traceback (most recent call last):
 | 
					
						
							| 
									
										
										
										
											2016-09-30 15:38:48 -04:00
										 |  |  |      File "<stdin>", line 2, in <module>
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  |    KeyboardInterrupt
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-06 23:16:48 +01:00
										 |  |  | If a :keyword:`finally` clause is present, the :keyword:`!finally`
 | 
					
						
							|  |  |  | clause will execute as the last task before the :keyword:`try`
 | 
					
						
							|  |  |  | statement completes. The :keyword:`!finally` clause runs whether or
 | 
					
						
							|  |  |  | not the :keyword:`!try` statement produces an exception. The following
 | 
					
						
							|  |  |  | points discuss more complex cases when an exception occurs:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | * If an exception occurs during execution of the :keyword:`!try`
 | 
					
						
							|  |  |  |   clause, the exception may be handled by an :keyword:`except`
 | 
					
						
							|  |  |  |   clause. If the exception is not handled by an :keyword:`!except`
 | 
					
						
							|  |  |  |   clause, the exception is re-raised after the :keyword:`!finally`
 | 
					
						
							|  |  |  |   clause has been executed.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | * An exception could occur during execution of an :keyword:`!except`
 | 
					
						
							|  |  |  |   or :keyword:`!else` clause. Again, the exception is re-raised after
 | 
					
						
							|  |  |  |   the :keyword:`!finally` clause has been executed.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-04 14:36:01 +02:00
										 |  |  | * If the :keyword:`!finally` clause executes a :keyword:`break`,
 | 
					
						
							|  |  |  |   :keyword:`continue` or :keyword:`return` statement, exceptions are not
 | 
					
						
							|  |  |  |   re-raised.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-06 23:16:48 +01:00
										 |  |  | * If the :keyword:`!try` statement reaches a :keyword:`break`,
 | 
					
						
							|  |  |  |   :keyword:`continue` or :keyword:`return` statement, the
 | 
					
						
							|  |  |  |   :keyword:`!finally` clause will execute just prior to the
 | 
					
						
							|  |  |  |   :keyword:`!break`, :keyword:`!continue` or :keyword:`!return`
 | 
					
						
							|  |  |  |   statement's execution.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | * If a :keyword:`!finally` clause includes a :keyword:`!return`
 | 
					
						
							|  |  |  |   statement, the returned value will be the one from the
 | 
					
						
							|  |  |  |   :keyword:`!finally` clause's :keyword:`!return` statement, not the
 | 
					
						
							|  |  |  |   value from the :keyword:`!try` clause's :keyword:`!return`
 | 
					
						
							|  |  |  |   statement.
 | 
					
						
							| 
									
										
										
										
											2019-09-11 10:37:13 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | For example::
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-19 01:24:29 -04:00
										 |  |  |    >>> def bool_return():
 | 
					
						
							| 
									
										
										
										
											2019-09-11 10:37:13 -05:00
										 |  |  |    ...     try:
 | 
					
						
							|  |  |  |    ...         return True
 | 
					
						
							|  |  |  |    ...     finally:
 | 
					
						
							|  |  |  |    ...         return False
 | 
					
						
							|  |  |  |    ...
 | 
					
						
							|  |  |  |    >>> bool_return()
 | 
					
						
							|  |  |  |    False
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | A more complicated example::
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |    >>> def divide(x, y):
 | 
					
						
							|  |  |  |    ...     try:
 | 
					
						
							|  |  |  |    ...         result = x / y
 | 
					
						
							|  |  |  |    ...     except ZeroDivisionError:
 | 
					
						
							| 
									
										
										
										
											2007-08-31 03:25:11 +00:00
										 |  |  |    ...         print("division by zero!")
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  |    ...     else:
 | 
					
						
							| 
									
										
										
										
											2007-08-31 03:25:11 +00:00
										 |  |  |    ...         print("result is", result)
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  |    ...     finally:
 | 
					
						
							| 
									
										
										
										
											2007-08-31 03:25:11 +00:00
										 |  |  |    ...         print("executing finally clause")
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  |    ...
 | 
					
						
							|  |  |  |    >>> divide(2, 1)
 | 
					
						
							| 
									
										
										
										
											2009-05-17 08:14:39 +00:00
										 |  |  |    result is 2.0
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  |    executing finally clause
 | 
					
						
							|  |  |  |    >>> divide(2, 0)
 | 
					
						
							|  |  |  |    division by zero!
 | 
					
						
							|  |  |  |    executing finally clause
 | 
					
						
							|  |  |  |    >>> divide("2", "1")
 | 
					
						
							|  |  |  |    executing finally clause
 | 
					
						
							|  |  |  |    Traceback (most recent call last):
 | 
					
						
							| 
									
										
										
										
											2016-09-30 15:38:48 -04:00
										 |  |  |      File "<stdin>", line 1, in <module>
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  |      File "<stdin>", line 3, in divide
 | 
					
						
							|  |  |  |    TypeError: unsupported operand type(s) for /: 'str' and 'str'
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | As you can see, the :keyword:`finally` clause is executed in any event.  The
 | 
					
						
							|  |  |  | :exc:`TypeError` raised by dividing two strings is not handled by the
 | 
					
						
							| 
									
										
										
										
											2018-12-19 08:09:46 +02:00
										 |  |  | :keyword:`except` clause and therefore re-raised after the :keyword:`!finally`
 | 
					
						
							| 
									
										
											  
											
												Merged revisions 66457-66459,66465-66468,66483-66485,66487-66491 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
  r66457 | antoine.pitrou | 2008-09-13 15:30:30 -0500 (Sat, 13 Sep 2008) | 5 lines
  Issue #3850: Misc/find_recursionlimit.py was broken.
  Reviewed by A.M. Kuchling.
........
  r66458 | benjamin.peterson | 2008-09-13 17:54:43 -0500 (Sat, 13 Sep 2008) | 1 line
  fix a name issue; note all doc files should be encoded in utf8
........
  r66459 | benjamin.peterson | 2008-09-14 11:02:22 -0500 (Sun, 14 Sep 2008) | 1 line
  clarify that radix for int is not 'guessed'
........
  r66465 | skip.montanaro | 2008-09-14 21:03:05 -0500 (Sun, 14 Sep 2008) | 3 lines
  Review usage.  Fix a mistake in the new-style class definition.  Add a
  couple new definitions (CPython and virtual machine).
........
  r66466 | skip.montanaro | 2008-09-14 21:19:53 -0500 (Sun, 14 Sep 2008) | 2 lines
  Pick up a few more definitions from the glossary on the wiki.
........
  r66467 | benjamin.peterson | 2008-09-14 21:53:23 -0500 (Sun, 14 Sep 2008) | 1 line
  mention that object.__init__ no longer takes arbitrary args and kwargs
........
  r66468 | andrew.kuchling | 2008-09-15 08:08:32 -0500 (Mon, 15 Sep 2008) | 1 line
  Rewrite item a bit
........
  r66483 | georg.brandl | 2008-09-16 05:17:45 -0500 (Tue, 16 Sep 2008) | 2 lines
  Fix typo.
........
  r66484 | benjamin.peterson | 2008-09-16 16:20:28 -0500 (Tue, 16 Sep 2008) | 2 lines
  be less wordy
........
  r66485 | georg.brandl | 2008-09-17 03:45:54 -0500 (Wed, 17 Sep 2008) | 2 lines
  #3888: add some deprecated modules in whatsnew.
........
  r66487 | skip.montanaro | 2008-09-17 06:50:36 -0500 (Wed, 17 Sep 2008) | 2 lines
  usage
........
  r66488 | andrew.kuchling | 2008-09-17 07:57:04 -0500 (Wed, 17 Sep 2008) | 1 line
  Markup fixes
........
  r66489 | andrew.kuchling | 2008-09-17 07:58:22 -0500 (Wed, 17 Sep 2008) | 2 lines
  Remove comment about improvement: pystone is about the same, and
  the improvements seem to be difficult to quantify
........
  r66490 | andrew.kuchling | 2008-09-17 08:04:53 -0500 (Wed, 17 Sep 2008) | 1 line
  Note sqlite3 version; move item
........
  r66491 | benjamin.peterson | 2008-09-17 16:54:56 -0500 (Wed, 17 Sep 2008) | 1 line
  document compileall command flags
........
											
										 
											2008-09-17 22:25:09 +00:00
										 |  |  | clause has been executed.
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | In real world applications, the :keyword:`finally` clause is useful for
 | 
					
						
							|  |  |  | releasing external resources (such as files or network connections), regardless
 | 
					
						
							|  |  |  | of whether the use of the resource was successful.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .. _tut-cleanup-with:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Predefined Clean-up Actions
 | 
					
						
							|  |  |  | ===========================
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Some objects define standard clean-up actions to be undertaken when the object
 | 
					
						
							|  |  |  | is no longer needed, regardless of whether or not the operation using the object
 | 
					
						
							|  |  |  | succeeded or failed. Look at the following example, which tries to open a file
 | 
					
						
							|  |  |  | and print its contents to the screen. ::
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    for line in open("myfile.txt"):
 | 
					
						
							| 
									
										
										
										
											2012-12-08 17:59:03 +02:00
										 |  |  |        print(line, end="")
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | The problem with this code is that it leaves the file open for an indeterminate
 | 
					
						
							| 
									
										
										
										
											2009-01-03 21:18:54 +00:00
										 |  |  | amount 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 larger
 | 
					
						
							|  |  |  | applications. The :keyword:`with` statement allows objects like files to be
 | 
					
						
							| 
									
										
										
										
											2007-08-31 03:25:11 +00:00
										 |  |  | used in a way that ensures they are always cleaned up promptly and correctly. ::
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |    with open("myfile.txt") as f:
 | 
					
						
							|  |  |  |        for line in f:
 | 
					
						
							| 
									
										
										
										
											2012-12-08 17:59:03 +02:00
										 |  |  |            print(line, end="")
 | 
					
						
							| 
									
										
										
										
											2007-08-15 14:28:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | After the statement is executed, the file *f* is always closed, even if a
 | 
					
						
							| 
									
										
										
										
											2007-08-31 03:25:11 +00:00
										 |  |  | problem was encountered while processing the lines. Objects which, like files,
 | 
					
						
							|  |  |  | provide predefined clean-up actions will indicate this in their documentation.
 | 
					
						
							| 
									
										
										
										
											2022-01-06 19:05:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .. _tut-exception-groups:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Raising and Handling Multiple Unrelated Exceptions
 | 
					
						
							|  |  |  | ==================================================
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | There are situations where it is necessary to report several exceptions that
 | 
					
						
							| 
									
										
										
										
											2022-11-06 00:03:29 +03:00
										 |  |  | have occurred. This is often the case in concurrency frameworks, when several
 | 
					
						
							| 
									
										
										
										
											2022-01-06 19:05:34 +00:00
										 |  |  | tasks may have failed in parallel, but there are also other use cases where
 | 
					
						
							|  |  |  | it is desirable to continue execution and collect multiple errors rather than
 | 
					
						
							|  |  |  | raise the first exception.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The builtin :exc:`ExceptionGroup` wraps a list of exception instances so
 | 
					
						
							|  |  |  | that they can be raised together. It is an exception itself, so it can be
 | 
					
						
							|  |  |  | caught like any other exception. ::
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    >>> def f():
 | 
					
						
							|  |  |  |    ...     excs = [OSError('error 1'), SystemError('error 2')]
 | 
					
						
							|  |  |  |    ...     raise ExceptionGroup('there were problems', excs)
 | 
					
						
							|  |  |  |    ...
 | 
					
						
							|  |  |  |    >>> f()
 | 
					
						
							|  |  |  |      + Exception Group Traceback (most recent call last):
 | 
					
						
							|  |  |  |      |   File "<stdin>", line 1, in <module>
 | 
					
						
							|  |  |  |      |   File "<stdin>", line 3, in f
 | 
					
						
							|  |  |  |      | ExceptionGroup: there were problems
 | 
					
						
							|  |  |  |      +-+---------------- 1 ----------------
 | 
					
						
							|  |  |  |        | OSError: error 1
 | 
					
						
							|  |  |  |        +---------------- 2 ----------------
 | 
					
						
							|  |  |  |        | SystemError: error 2
 | 
					
						
							|  |  |  |        +------------------------------------
 | 
					
						
							|  |  |  |    >>> try:
 | 
					
						
							|  |  |  |    ...     f()
 | 
					
						
							|  |  |  |    ... except Exception as e:
 | 
					
						
							|  |  |  |    ...     print(f'caught {type(e)}: e')
 | 
					
						
							|  |  |  |    ...
 | 
					
						
							|  |  |  |    caught <class 'ExceptionGroup'>: e
 | 
					
						
							|  |  |  |    >>>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | By using ``except*`` instead of ``except``, we can selectively
 | 
					
						
							|  |  |  | handle only the exceptions in the group that match a certain
 | 
					
						
							|  |  |  | type. In the following example, which shows a nested exception
 | 
					
						
							|  |  |  | group, each ``except*`` clause extracts from the group exceptions
 | 
					
						
							|  |  |  | of a certain type while letting all other exceptions propagate to
 | 
					
						
							|  |  |  | other clauses and eventually to be reraised. ::
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    >>> def f():
 | 
					
						
							| 
									
										
										
										
											2023-07-22 08:19:30 -04:00
										 |  |  |    ...     raise ExceptionGroup(
 | 
					
						
							|  |  |  |    ...         "group1",
 | 
					
						
							|  |  |  |    ...         [
 | 
					
						
							|  |  |  |    ...             OSError(1),
 | 
					
						
							|  |  |  |    ...             SystemError(2),
 | 
					
						
							|  |  |  |    ...             ExceptionGroup(
 | 
					
						
							|  |  |  |    ...                 "group2",
 | 
					
						
							|  |  |  |    ...                 [
 | 
					
						
							|  |  |  |    ...                     OSError(3),
 | 
					
						
							|  |  |  |    ...                     RecursionError(4)
 | 
					
						
							|  |  |  |    ...                 ]
 | 
					
						
							|  |  |  |    ...             )
 | 
					
						
							|  |  |  |    ...         ]
 | 
					
						
							|  |  |  |    ...     )
 | 
					
						
							| 
									
										
										
										
											2022-01-06 19:05:34 +00:00
										 |  |  |    ...
 | 
					
						
							|  |  |  |    >>> try:
 | 
					
						
							|  |  |  |    ...     f()
 | 
					
						
							|  |  |  |    ... except* OSError as e:
 | 
					
						
							|  |  |  |    ...     print("There were OSErrors")
 | 
					
						
							|  |  |  |    ... except* SystemError as e:
 | 
					
						
							|  |  |  |    ...     print("There were SystemErrors")
 | 
					
						
							|  |  |  |    ...
 | 
					
						
							|  |  |  |    There were OSErrors
 | 
					
						
							|  |  |  |    There were SystemErrors
 | 
					
						
							|  |  |  |      + Exception Group Traceback (most recent call last):
 | 
					
						
							|  |  |  |      |   File "<stdin>", line 2, in <module>
 | 
					
						
							|  |  |  |      |   File "<stdin>", line 2, in f
 | 
					
						
							|  |  |  |      | ExceptionGroup: group1
 | 
					
						
							|  |  |  |      +-+---------------- 1 ----------------
 | 
					
						
							|  |  |  |        | ExceptionGroup: group2
 | 
					
						
							|  |  |  |        +-+---------------- 1 ----------------
 | 
					
						
							|  |  |  |          | RecursionError: 4
 | 
					
						
							|  |  |  |          +------------------------------------
 | 
					
						
							|  |  |  |    >>>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Note that the exceptions nested in an exception group must be instances,
 | 
					
						
							|  |  |  | not types. This is because in practice the exceptions would typically
 | 
					
						
							|  |  |  | be ones that have already been raised and caught by the program, along
 | 
					
						
							|  |  |  | the following pattern::
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    >>> excs = []
 | 
					
						
							|  |  |  |    ... for test in tests:
 | 
					
						
							|  |  |  |    ...     try:
 | 
					
						
							|  |  |  |    ...         test.run()
 | 
					
						
							|  |  |  |    ...     except Exception as e:
 | 
					
						
							|  |  |  |    ...         excs.append(e)
 | 
					
						
							|  |  |  |    ...
 | 
					
						
							|  |  |  |    >>> if excs:
 | 
					
						
							|  |  |  |    ...    raise ExceptionGroup("Test Failures", excs)
 | 
					
						
							|  |  |  |    ...
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-20 13:43:10 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-06 00:41:04 -05:00
										 |  |  | .. _tut-exception-notes:
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-20 13:43:10 +01:00
										 |  |  | Enriching Exceptions with Notes
 | 
					
						
							|  |  |  | ===============================
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | When an exception is created in order to be raised, it is usually initialized
 | 
					
						
							|  |  |  | with information that describes the error that has occurred. There are cases
 | 
					
						
							|  |  |  | where it is useful to add information after the exception was caught. For this
 | 
					
						
							|  |  |  | purpose, exceptions have a method ``add_note(note)`` that accepts a string and
 | 
					
						
							|  |  |  | adds it to the exception's notes list. The standard traceback rendering
 | 
					
						
							|  |  |  | includes all notes, in the order they were added, after the exception. ::
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    >>> try:
 | 
					
						
							|  |  |  |    ...     raise TypeError('bad type')
 | 
					
						
							|  |  |  |    ... except Exception as e:
 | 
					
						
							|  |  |  |    ...     e.add_note('Add some information')
 | 
					
						
							|  |  |  |    ...     e.add_note('Add some more information')
 | 
					
						
							|  |  |  |    ...     raise
 | 
					
						
							|  |  |  |    ...
 | 
					
						
							|  |  |  |    Traceback (most recent call last):
 | 
					
						
							|  |  |  |      File "<stdin>", line 2, in <module>
 | 
					
						
							|  |  |  |    TypeError: bad type
 | 
					
						
							|  |  |  |    Add some information
 | 
					
						
							|  |  |  |    Add some more information
 | 
					
						
							|  |  |  |    >>>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | For example, when collecting exceptions into an exception group, we may want
 | 
					
						
							|  |  |  | to add context information for the individual errors. In the following each
 | 
					
						
							|  |  |  | exception in the group has a note indicating when this error has occurred. ::
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    >>> def f():
 | 
					
						
							|  |  |  |    ...     raise OSError('operation failed')
 | 
					
						
							|  |  |  |    ...
 | 
					
						
							|  |  |  |    >>> excs = []
 | 
					
						
							|  |  |  |    >>> for i in range(3):
 | 
					
						
							|  |  |  |    ...     try:
 | 
					
						
							|  |  |  |    ...         f()
 | 
					
						
							|  |  |  |    ...     except Exception as e:
 | 
					
						
							|  |  |  |    ...         e.add_note(f'Happened in Iteration {i+1}')
 | 
					
						
							|  |  |  |    ...         excs.append(e)
 | 
					
						
							|  |  |  |    ...
 | 
					
						
							|  |  |  |    >>> raise ExceptionGroup('We have some problems', excs)
 | 
					
						
							|  |  |  |      + Exception Group Traceback (most recent call last):
 | 
					
						
							|  |  |  |      |   File "<stdin>", line 1, in <module>
 | 
					
						
							|  |  |  |      | ExceptionGroup: We have some problems (3 sub-exceptions)
 | 
					
						
							|  |  |  |      +-+---------------- 1 ----------------
 | 
					
						
							|  |  |  |        | Traceback (most recent call last):
 | 
					
						
							|  |  |  |        |   File "<stdin>", line 3, in <module>
 | 
					
						
							|  |  |  |        |   File "<stdin>", line 2, in f
 | 
					
						
							|  |  |  |        | OSError: operation failed
 | 
					
						
							|  |  |  |        | Happened in Iteration 1
 | 
					
						
							|  |  |  |        +---------------- 2 ----------------
 | 
					
						
							|  |  |  |        | Traceback (most recent call last):
 | 
					
						
							|  |  |  |        |   File "<stdin>", line 3, in <module>
 | 
					
						
							|  |  |  |        |   File "<stdin>", line 2, in f
 | 
					
						
							|  |  |  |        | OSError: operation failed
 | 
					
						
							|  |  |  |        | Happened in Iteration 2
 | 
					
						
							|  |  |  |        +---------------- 3 ----------------
 | 
					
						
							|  |  |  |        | Traceback (most recent call last):
 | 
					
						
							|  |  |  |        |   File "<stdin>", line 3, in <module>
 | 
					
						
							|  |  |  |        |   File "<stdin>", line 2, in f
 | 
					
						
							|  |  |  |        | OSError: operation failed
 | 
					
						
							|  |  |  |        | Happened in Iteration 3
 | 
					
						
							|  |  |  |        +------------------------------------
 | 
					
						
							|  |  |  |    >>>
 |