mirror of
https://github.com/python/cpython.git
synced 2025-10-26 08:19:20 +00:00
gh-90449: Improve accuracy and readability of exceptions tutorial (GH-31899)
This commit is contained in:
parent
3fc57e8f6f
commit
04f9658c59
1 changed files with 54 additions and 46 deletions
|
|
@ -147,10 +147,52 @@ For example, the following code will print B, C, D in that order::
|
||||||
Note that if the *except clauses* were reversed (with ``except B`` first), it
|
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.
|
would have printed B, B, B --- the first matching *except clause* is triggered.
|
||||||
|
|
||||||
All exceptions inherit from :exc:`BaseException`, and so it can be used to serve
|
When an exception occurs, it may have associated values, also known as the
|
||||||
as a wildcard. Use this with extreme caution, since it is easy to mask a real
|
exception's *arguments*. The presence and types of the arguments depend on the
|
||||||
programming error in this way! It can also be used to print an error message and
|
exception type.
|
||||||
then re-raise the exception (allowing a caller to handle the exception as well)::
|
|
||||||
|
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
|
||||||
|
types define :meth:`__str__` to print all the arguments without explicitly
|
||||||
|
accessing ``.args``. ::
|
||||||
|
|
||||||
|
>>> try:
|
||||||
|
... raise Exception('spam', 'eggs')
|
||||||
|
... except Exception as inst:
|
||||||
|
... print(type(inst)) # the exception instance
|
||||||
|
... print(inst.args) # arguments stored in .args
|
||||||
|
... print(inst) # __str__ allows args to be printed directly,
|
||||||
|
... # but may be overridden in exception subclasses
|
||||||
|
... x, y = inst.args # unpack args
|
||||||
|
... print('x =', x)
|
||||||
|
... print('y =', y)
|
||||||
|
...
|
||||||
|
<class 'Exception'>
|
||||||
|
('spam', 'eggs')
|
||||||
|
('spam', 'eggs')
|
||||||
|
x = spam
|
||||||
|
y = eggs
|
||||||
|
|
||||||
|
The exception's :meth:`__str__` output is printed as the last part ('detail')
|
||||||
|
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)::
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
@ -159,16 +201,13 @@ then re-raise the exception (allowing a caller to handle the exception as well):
|
||||||
s = f.readline()
|
s = f.readline()
|
||||||
i = int(s.strip())
|
i = int(s.strip())
|
||||||
except OSError as err:
|
except OSError as err:
|
||||||
print("OS error: {0}".format(err))
|
print("OS error:", err)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
print("Could not convert data to an integer.")
|
print("Could not convert data to an integer.")
|
||||||
except BaseException as err:
|
except Exception as err:
|
||||||
print(f"Unexpected {err=}, {type(err)=}")
|
print(f"Unexpected {err=}, {type(err)=}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
Alternatively the last except clause may omit the exception name(s), however the exception
|
|
||||||
value must then be retrieved with ``sys.exception()``.
|
|
||||||
|
|
||||||
The :keyword:`try` ... :keyword:`except` statement has an optional *else
|
The :keyword:`try` ... :keyword:`except` statement has an optional *else
|
||||||
clause*, which, when present, must follow all *except clauses*. It is useful
|
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 code that must be executed if the *try clause* does not raise an exception.
|
||||||
|
|
@ -188,39 +227,8 @@ the :keyword:`try` clause because it avoids accidentally catching an exception
|
||||||
that wasn't raised by the code being protected by the :keyword:`!try` ...
|
that wasn't raised by the code being protected by the :keyword:`!try` ...
|
||||||
:keyword:`!except` statement.
|
:keyword:`!except` statement.
|
||||||
|
|
||||||
When an exception occurs, it may have an associated value, also known as the
|
Exception handlers do not handle only exceptions that occur immediately in the
|
||||||
exception's *argument*. The presence and type of the argument depend on the
|
*try clause*, but also those that occur inside functions that are called (even
|
||||||
exception type.
|
|
||||||
|
|
||||||
The *except clause* may specify a variable after the exception name. The
|
|
||||||
variable is bound to an exception instance with the arguments stored in
|
|
||||||
``instance.args``. For convenience, the exception instance defines
|
|
||||||
:meth:`__str__` so the arguments can be printed directly without having to
|
|
||||||
reference ``.args``. One may also instantiate an exception first before
|
|
||||||
raising it and add any attributes to it as desired. ::
|
|
||||||
|
|
||||||
>>> try:
|
|
||||||
... raise Exception('spam', 'eggs')
|
|
||||||
... except Exception as inst:
|
|
||||||
... print(type(inst)) # the exception instance
|
|
||||||
... print(inst.args) # arguments stored in .args
|
|
||||||
... print(inst) # __str__ allows args to be printed directly,
|
|
||||||
... # but may be overridden in exception subclasses
|
|
||||||
... x, y = inst.args # unpack args
|
|
||||||
... print('x =', x)
|
|
||||||
... print('y =', y)
|
|
||||||
...
|
|
||||||
<class 'Exception'>
|
|
||||||
('spam', 'eggs')
|
|
||||||
('spam', 'eggs')
|
|
||||||
x = spam
|
|
||||||
y = eggs
|
|
||||||
|
|
||||||
If an exception has arguments, they are printed as the last part ('detail') of
|
|
||||||
the message for unhandled exceptions.
|
|
||||||
|
|
||||||
Exception handlers don't just handle exceptions if they occur immediately in the
|
|
||||||
*try clause*, but also if they occur inside functions that are called (even
|
|
||||||
indirectly) in the *try clause*. For example::
|
indirectly) in the *try clause*. For example::
|
||||||
|
|
||||||
>>> def this_fails():
|
>>> def this_fails():
|
||||||
|
|
@ -249,8 +257,9 @@ exception to occur. For example::
|
||||||
|
|
||||||
The sole argument to :keyword:`raise` indicates the exception to be raised.
|
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
|
This must be either an exception instance or an exception class (a class that
|
||||||
derives from :class:`Exception`). If an exception class is passed, it will
|
derives from :class:`BaseException`, such as :exc:`Exception` or one of its
|
||||||
be implicitly instantiated by calling its constructor with no arguments::
|
subclasses). If an exception class is passed, it will be implicitly
|
||||||
|
instantiated by calling its constructor with no arguments::
|
||||||
|
|
||||||
raise ValueError # shorthand for 'raise ValueError()'
|
raise ValueError # shorthand for 'raise ValueError()'
|
||||||
|
|
||||||
|
|
@ -335,8 +344,7 @@ Most exceptions are defined with names that end in "Error", similar to the
|
||||||
naming of the standard exceptions.
|
naming of the standard exceptions.
|
||||||
|
|
||||||
Many standard modules define their own exceptions to report errors that may
|
Many standard modules define their own exceptions to report errors that may
|
||||||
occur in functions they define. More information on classes is presented in
|
occur in functions they define.
|
||||||
chapter :ref:`tut-classes`.
|
|
||||||
|
|
||||||
|
|
||||||
.. _tut-cleanup:
|
.. _tut-cleanup:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue