Exceptions are unexpected errors Zope encounters during the rendering of a DTML statement. Once an exception is detected, the normal execution of the DTML stops. Consider the following example:
Cost per unit: $<dtml-var expr="_.float(total_cost/total_units)">
This statement functions normally if total_units is not zero. However, in the event that total_units is zero, a ZeroDivisionError exception is raised indicating an illegal operation. Thus, rather than rendering the DTML, an error message will be returned.
DTML provides the dtml-try tag to catch and handle these problematic exceptions within a block of DTML code. This allows you to anticipate and handle errors yourself, rather than getting a Zope error message whenever an exception occurs.
As an exception handler, the dtml-try tag has two functions. First, if an exception is raised, the dtml-try tag gains control of execution and handles the exception appropriately, and thus avoids returning a Zope error message. Second, the dtml-try tag allows the rendering of any subsequent DMTL to continue.
Within the dtml-try tag are one or more dtml-except tags that identify and handle different exceptions. When an exception is raised, each dtml-except tag is checked in turn to see if it matches the exception's type. The first dtml-except tag to match handles the exception. If no exceptions are given in a dtml-except tag, then the dtml-except tag will match all exceptions.
Implementing the dtml-try tag in the example above would resemble:
Cost per unit: $<dtml-var expr="_.float(total_cost/total_units")>
Cost per unit: N/A
If a ZeroDivisionError is raised, control goes to the dtml-except tag, and "Cost per unit: N/A" is rendered. Once the statements of the dtml-except tag finish, execution of DTML continues past the dtml-try block.
DTML's except tags work with Python's class-based exceptions. In addition to matching exceptions by name, the dtml-except tag will match any subclass of the named exception. For example, if ArithmaticError is named in a dtml-except tag, the tag can handle all ArithmaticError subclasses including, ZeroDivisionError.
Inside the body of a dtml-except tag you can access information about the handled exception through several special variables. These variables are:
The dtml-try tag has an optional dtml-else block that is rendered if an exception didn't occur. The exceptions in the else block are not handled by the preceding dtml-except blocks. Implementing the dtml-else tag with the dtml-try tag would be like:
<dtml-except SomeError AnotherError>
The first dtml-except block to match the type of error raised is rendered. If a dtml-except block has no name, then it matches all raised errors. The optional dtml-else block is rendered when no exception occurs in the dtml-try block. Exception in the dtml-else block are not handled by the preceding dtml-except blocks.
In addition to the dtml-else block, the dtml-try tag has the ability to use a dtml-finally block that is always rendered whether an exception occurs or not. The dtml-finally form specifies a cleanup block to be rendered even when a exception occurs. Note, any rendered results are discarded if an exception occurs in either the try or finally blocks. The dtml-finally block is only of any used if you need to clean up something that will not be cleaned up by the transaction abort code. The dtml-finally block will always be called, whether there is an exception or nor and whether a return tage is used or not. If you use a dtml-return tag in the try block, any output of the dtml-finally block is discarded.
<dtml-try> <dtml-finally> </dtml-try>
Important to note, if a exception occurs in the dtml-try block and an exception occurs in the dtml-finally block any information about the first exception is lost. It follows that if a return tag is used in the dtml-try block and an exception occurs in the dtml-finally block, the result returned in the dtml-try block will be lost. Also, if a return tag is used in the dtml-finally block, the result returned in the dtml-try block will be lost as well.Previous Chapter | Next Chapter | Up | Next Section | Contents