Error handling with Python script tools

3186
4
07-18-2011 06:54 AM
AliceDeschamps1
New Contributor
I am trying to integrate some error handling in my python script tools but I am not exactly sure how to do it properly.  The desktop help has a lot of great examples but there are so many different ways of doing this.   I am also a bit confused with the difference between error messaging in standalone script vs script tools??

http://help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#//002z0000000q000000.htm

Below is a subset of my script, only showing the error handling portion.

# Import arcpy module
import arcpy
from arcpy import env
from arcpy.sa import *
import sys, string, os
arcpy.env.overwriteOutput = True

try:
    # Check out any necessary licenses
    if arcpy.CheckProduct("ArcInfo") == "Unavailable":
        arcpy.AddError("ArcInfo Licensing Issue")
        raise LicenseError
    if arcpy.CheckExtension("Spatial") == "Available":
        arcpy.CheckOutExtension("Spatial")
    else:
        arcpy.AddError("Spatial Analyst Licensing Issue")
        raise LicenseError

# all all the processing here....


except:
    print arcpy.GetMessages(2)
finally:
    # Check in the Spatial Analyst extension
    arcpy.CheckInExtension("Spatial")      


Questions:
-Will the above work properly for script tools?  For the except: block will the print do anything in script tools or do I need to use some other syntax to print the error instead?
-In this particular tool I have a cleanup routine that deletes intermediate files.  I currently have this before the except statement but would like to make sure that if the tool crashes that it cleans-up the intermediate files.  Is it possible to put the cleanup routine within the finally: block?  Is that good coding practice?

Any tips on simple and best practice for error handling in script tools (containing a series of geoprocessing steps) would be greatly appreciated.

Thanks.

Alice
Tags (2)
0 Kudos
4 Replies
LoganPugh
Occasional Contributor III
Take a look at this Geoprocessing Blog post: http://blogs.esri.com/Dev/blogs/geoprocessing/archive/2008/12/01/Tips-and-tricks-_2D00_-Error-handli...

With regards to the print command, it will not work in script tools, you need to use arcpy.AddMessage/AddWarning/AddError instead. What I usually do is have functions for messages, warnings, and errors, that does both. E.g.:

def message(msg):
    print msg
    gp.AddMessage(msg)

def warning(msg):
    print msg
    gp.AddWarning(msg)

def error(msg):
    print msg
    gp.AddError(msg)


Just switch out the gp for arcpy since you're using that. There may be better ways to do this (e.g. the logging module as suggested here: http://forums.arcgis.com/threads/4719-Dumb-question-can-I-write-standalone-python-script-to-run-with...) but this is simple enough for me.

And yes, the finally clause is the best place to put cleanup code that is to be executed whether an error occurs or not.
0 Kudos
AliceDeschamps1
New Contributor
Thanks for the clarifications and the link.
0 Kudos
AliceDeschamps1
New Contributor
I find the traceback functionality very useful and I adapted the scripts examples from the suggested blog link below for ArcGISv10.  I included a snippet of the modified working script.
http://blogs.esri.com/dev/blogs/geoprocessing/archive/2008/12/01/tips-and-tricks-_2d00_-error-handli...

I noticed in that the blog uses the "def trace():"  inside (tip#4) or outside (tip#5) the try block?   What is the logic for putting it inside vs. outside?  


# Import system module
from xml.etree import ElementTree
import arcpy, string, os

def trace():
    import sys, traceback
    tb = sys.exc_info()[2]
    tbinfo = traceback.format_tb(tb)[0] 
    line = tbinfo.split(", ")[1]
    filename = sys.path[0] + os.sep + "test.py"
    synerror = traceback.format_exc().splitlines()[-1]
    return line, filename, synerror

if __name__ == '__main__':


    try:
        inShapeFile= arcpy.GetParameterAsText(0) #final edited polygon shapefile
        inFile=arcpy.GetParameterAsText(1) #for R1 is .txt, for R2 is .xml
        polList=str(arcpy.GetParameterAsText(2))#user select from drop list
        
        # all the processing code goes here.....

   except arcpy.ExecuteError:
        #Return Geoprocessing tool specific errors
        line, filename, err = trace()
        arcpy.AddError("Geoprocessing error on " + line + " of " + filename + " :")
        for msg in range(0, arcpy.GetMessageCount()):
            if arcpy.GetSeverity(msg) == 2:
                arcpy.AddReturnMessage(msg)
    except:
        #Gets non-tool errors
        line, filename, err = trace()
        arcpy.AddError("Python error on " + line + " of " + filename)
        arcpy.AddError(err)  
0 Kudos
LoganPugh
Occasional Contributor III

I noticed in that the blog uses the "def trace():"  inside (tip#4) or outside (tip#5) the try block?   What is the logic for putting it inside vs. outside?  


That's a good question, I hadn't noticed that. I'm not sure, but it looks like a logic error on the author's part. Normally wouldn't want to define a function inside of a try.
0 Kudos