• Facing Errors In Python - Part 6




    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 RunRun 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 RunRun 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 RunRun 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 RunRun 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

    Powered by Blogger.

    Tags

    Popular Posts