Passing error information to the caller
Python provides exceptionally flexible error handling in that you
can pass information to the caller (the code that is calling your code) no
matter which exception you use. Of course, the caller may not know that the
information is available, which leads to a lot of discussion on the topic. If
you’re working with someone else’s code and don’t know whether additional
information is available, you can always use the technique described in the
“Obtaining a list of exception arguments” sidebar earlier in this Post to find
it.
You may have wondered whether you could provide better information
when working with a ValueError exception than with an exception provided
natively by Python. The following steps show that you can modify the output so
that it does include helpful information.
Open a Python File window.
You see an editor in which you can type the example code.
Type the following code
into the window — pressing Enter after each line:
try:
Ex = ValueError()
Ex.strerror = "Value must be within 1 and 10." raise Ex
except ValueError as e:
print("ValueError Exception!", e.strerror)
The ValueError exception normally doesn’t provide an attribute
named strerror (a common name for string error), but you can add it simply by
assigning a value to it as shown. When the example raises the exception, the
except clause handles it as usual but obtains access to the attributes using e.
You can then access the e.strerror member to obtain the added information.
Choose Run➪Run Module.
You see a Python Shell window open. The application displays an
expanded ValueError exception
Creating and Using Custom Exceptions
Python provides a wealth of standard exceptions that you should
use when-ever possible. These exceptions are incredibly flexible, and you can
even modify them as needed (within reason) to meet specific needs. For example,
the “Passing error information to the caller” section of this Post
demon-strates how to modify a ValueError exception to allow for additional
data. However, sometimes you simply must create a custom exception because none
of the standard exceptions will work. Perhaps the exception name just doesn’t
tell the viewer the purpose that the exception serves. You may need a custom
exception for specialized database work or when working with a service.
The example in this section shows a quick method for creating your
own exceptions. To perform this task, you must create a class that uses an
exist-ing exception as a starting point. To make things a little easier, this
example creates an exception that builds upon the functionality provided by the
ValueError exception. The advantage of using this approach rather than the one
shown in the “Passing error information to the caller” section, the preceding section
in this Post, is that this approach tells anyone who follows you precisely what
the addition to the ValueError exception is; additionally, it makes the
modified exception easier to use.
Open a Python File window.
You see an editor in which you can type the example code.
Type the following code
into the window — pressing Enter after each line:
class CustomValueError(ValueError): def __init__(self, arg):
self.strerror = arg self.args = {arg}
try:
raise CustomValueError("Value must be within 1 and 10.")
except CustomValueError as e: print("CustomValueError
Exception!", e.strerror)
This example essentially replicates the functionality of the
example in the “Passing error information to the caller” section of the Post.
However, it places the same error in both strerror and args so that the
developer has access to either (as would normally happen).
The code begins by creating the CustomValueError class that uses
the ValueError exception class as a starting point. The __init__() func-tion
provides the means for creating a new instance of that class. Think of the
class as a blueprint and the instance as the building created from the
blueprint.
Notice that the strerror attribute has the value assigned directly
to it, but args receives it as an array. The args member normally contains an
array of all the exception values, so this is standard procedure, even when
args contains just one value as it does now.
The code for using the exception is considerably easier than
modify-ing ValueError directly. All you do is call raise with the name of the
exception and the arguments you want to pass, all on one line.
Choose Run➪Run Module.
You see a Python Shell window open. The application displays the
letter sequence, along with the letter number.
Using the finally Clause
Normally you want to handle any exception that occurs in a way
that doesn’t cause the application to crash. However, sometimes you can’t do
anything to fix the problem, and the application is most definitely going to
crash. At this point, your goal is to cause the application to crash
gracefully, which means closing files so that the user doesn’t lose data and
performing other tasks of that nature. Anything you can do to keep damage to
data and the system to a minimum is an essential part of handling data for a
crashing application.
The finally clause is part of the crashing-application strategy.
You use this clause to perform any required last-minute tasks. Normally, the
finally clause is quite short and uses only calls that are likely to succeed
without further problem. It’s essential to close the files, log the user off,
and per-form other required tasks, and then let the application crash before
some-thing terrible happens (such as a total system failure). With this
necessity in mind, the following steps show a simple example of using the
finally clause.
Open a Python File window.
You see an editor in which you can type the example code.
Type the following code
into the window — pressing Enter after each line:
import sys
try:
raise ValueError print("Raising an exception.")
except ValueError: print("ValueError Exception!")
sys.exit()
finally:
print("Taking care of last minute details.")
print("This code will never execute.")
In this example, the code raises a ValueError exception. The
except clause executes as normal when this happens. The call to sys.exit()
means that the application exits after the exception is handled. Perhaps the
application can’t recover in this particular instance, but the applica-tion
normally ends, which is why the final print() function call won’t ever execute.
The finally clause code always executes. It doesn’t matter whether
the exception happens or not. The code you place in this block needs to be
common code that you always want to execute. For example, when working with a
file, you place the code to close the file into this block to ensure that the
data isn’t damaged by remaining in memory rather than going to disk.
Choose Run➪Run Module.
You see a Python Shell window open. The application displays the
except clause message and the finally clause message. The sys.exit() call
prevents any other code from executing.
Comment out the raise
ValueError call by preceding it with two pound signs, like this:
##raise ValueError
Removing the exception will demonstrate how the finally clause
actually works.
Save the file to disk to
ensure that Python sees the change.
Choose Run➪Run Module.
You see a Python Shell window open. The application displays a
series of messages, including the finally clause message. This part of the
example shows that the finally clause always executes, so you need to use it
carefully.
0 comments:
Post a Comment