Errors happen. Writing scripts that expect and handle errors can save time and frustration. When a tool returns an error message, ArcPy generates a system error or exception. In
Python
, you can provide a variety of structures and methods that can handle exceptions. Of course, a script can fail for other reasons not related to a geoprocessing tool. These also need to be caught and dealt with in an appropriate manner. The following sections offer a few techniques that introduce the basics of
Python
exception handling.
When a tool writes an error message, ArcPy generates an
arcpy.ExecuteError
exception.
Python
allows you to write a routine that automatically runs when a system error is generated. In this error-handling routine, retrieve the error message from ArcPy and react accordingly. If a script does not have an error-handling routine, it fails immediately, which decreases its robustness. Use error-handling routines to manage errors and improve a script's usability.
Geoprocessing tool error messages are accompanied by a six-digit code. These
ID codes have been documented
to provide additional information on their cause and how they can be dealt with.
try-except statement
A
try-except
statement can be used to wrap entire programs or just particular portions of code to trap and identify errors. If an error occurs within the
try
statement, an exception is raised, and the code under the except statement is executed. Using a basic except statement is the most basic form of error handling.
In the following code,
Buffer
fails because the required
buffer_distance_or_field
argument has not been provided. Instead of failing without explanation, the
except
statement is used to trap the error, then fetch and print the error message generated by
Buffer
. Note that the
except
block is only executed if
Buffer
returns an error.
import arcpy
import sys
# Execute the Buffer tool
arcpy.Buffer_analysis("c:/transport/roads.shp", "c:/transport/roads_buffer.shp")
except Exception:
e = sys.exc_info()[1]
print(e.args[0])
# If using this code within a script tool, AddError can be used to return messages
# back to a script tool. If not, AddError will have no effect.
arcpy.AddError(e.args[0])
The
try
statement has an optional
finally
clause that can be used for tasks that should always be executed, whether an exception occurs or not. In the following example, the
ArcGIS 3D Analyst extension
is checked in under a
finally
clause, ensuring that the extension is always checked in.
class LicenseError(Exception):
import arcpy
if arcpy.CheckExtension("3D") == "Available":
arcpy.CheckOutExtension("3D")
else:
# Raise a custom exception
raise LicenseError
arcpy.env.workspace = "D:/GrosMorne"
arcpy.HillShade_3d("WesternBrook", "westbrook_hill", 300)
arcpy.Aspect_3d("WesternBrook", "westbrook_aspect")
except LicenseError:
print "3D Analyst license is unavailable"
except arcpy.ExecuteError:
print(arcpy.GetMessages(2))
finally:
# Check in the 3D Analyst extension
arcpy.CheckInExtension("3D")
raise
statement
The previous example deals with an exception that occurred in the code. In some cases, it may be necessary to create custom exceptions. A
raise
statement can be used for this purpose. In the following code, a
raise
statement is used when an input feature class has been identified as having no features. This is not strictly an error but a condition that the code can be used to guard against.
class NoFeatures(Exception):
import arcpy
import os
import sys
arcpy.env.overwriteOutput = True
fc = arcpy.GetParameterAsText(0)
# Check that the input has features
result = arcpy.GetCount_management(fc)
if int(result[0]) > 0:
arcpy.FeatureToPolygon_management(
fc, os.path.join(os.path.dirname(fc), 'out_poly.shp'))
else:
# Raise custom exception
raise NoFeatures(result)
except NoFeatures:
# The input has no features
print('{} has no features'.format(fc))
except:
# By default any other errors will be caught here
e = sys.exc_info()[1]
print(e.args[0])
ExecuteError class
When a geoprocessing tool fails, it throws an
arcpy.ExecuteError
exception class,
which means that you can divide errors into different groups,
geoprocessing errors (those that throw the
arcpy.ExecuteError
exception) and other exception types. You
can then handle the errors differently, as demonstrated in the code
below:
import arcpy
import sys
result = arcpy.GetCount_management("C:/invalid.shp")
# Return geoprocessing specific errors
except arcpy.ExecuteError:
arcpy.AddError(arcpy.GetMessages(2))
# Return any other type of error
except:
# By default any other errors will be caught here
e = sys.exc_info()[1]
print(e.args[0])
traceback
In larger, more complex scripts, it can be difficult to determine the precise location of an error.
Python
's
sys
and
traceback
modules can be used together to isolate the exact location and cause of the error, identifying the cause of an error more accurately and saving valuable debugging time.
# Import the required modules
import arcpy
import sys
import traceback
arcpy.env.workspace = "C:/Data/myData.gdb"
arcpy.CreateSpatialReference_management()
#--------------------------
# Your code goes here
# See the table below for examples
#--------------------------
except arcpy.ExecuteError:
# Get the tool error messages
msgs = arcpy.GetMessages(2)
# Return tool error messages for use with a script tool
arcpy.AddError(msgs)
# Print tool error messages for use in Python
print(msgs)
except:
# Get the traceback object
tb = sys.exc_info()[2]
tbinfo = traceback.format_tb(tb)[0]
# Concatenate information together concerning the error into a message string
pymsg = "PYTHON ERRORS:\nTraceback info:\n" + tbinfo + "\nError Info:\n" + str(sys.exc_info()[1])
msgs = "ArcPy ERRORS:\n" + arcpy.GetMessages(2) + "\n"
# Return Python error messages for use in script tool or Python window
arcpy.AddError(pymsg)
arcpy.AddError(msgs)
# Print Python error messages for use in Python / Python window
print(pymsg)
print(msgs)
If the above code was used and a geoprocessing tool error occurred,
such an invalid input, this would raise
arcpy.ExecuteError
, and the first
except
statement would
be used. This statement would print the error messages using
the
GetMessages
function. If the same code was used, but a different
type of error occurred, the second
except
statement would be used.
Instead of printing geoprocessing messages, it gets a
traceback
object and prints the appropriate system error
messages.
The table below shows the expected errors that result from three different lines of codes that could be substituted into the code above. The first is a geoprocessing tool error, which prints out the traceback information and the geoprocessing error messages. The second and third examples are not specifically caught and print only the traceback information.
Your code
|
Resulting error
|
arcpy.GetCount_management("")
|
PYTHON ERRORS:
Traceback info:
File "c:\temp\errortest.py", line 10, in <module>
arcpy.GetCount_management("")
Error Info:
Failed to execute. Parameters are not valid.
ERROR 000735: Input Rows: value is required
Failed to execute (GetCount).
ArcPy ERRORS:
Failed to execute. Parameters are not valid.
ERROR 000735: Input Rows: value is required
Failed to execute (GetCount).
|
x = "a" + 1
|
PYTHON ERRORS:
Traceback info:
File "c:\temp\errortest.py", line 10, in <module>
x = "a" + 1
Error Info:
cannot concatenate 'str' and 'int' objects
|
float("a text string")
|
PYTHON ERRORS:
Traceback info:
File "c:\temp\errortest.py", line 10, in <module>
float("a text string")
Error Info:
invalid literal for float(): a text string
|
Error results
Getting error messages from a result object
A quick word about the
Result
object, shown below:
result = arcpy.GetCount_management("c:/data/rivers.shp")
If the call to
GetCount_management
raises an exception, the
Result
object is not created. This means you cannot retrieve error messages from the
Result
object.
import arcpy
result = arcpy.GetCount_management("c:/data/rivers.shp")
# Return Geoprocessing specific errors
# (this method is incorrect!)
except arcpy.ExecuteError:
arcpy.AddError(result.getMessages(2))
The above code fails with the message
name 'result' is not defined
. This is because the
Result
object could not be created due to the tool's failure. Since the
Result
object is not created, a
Python
error is raised when trying to use the
getMessages
method.
A
Result
object created by calling a geoprocessing service on
ArcGIS Server
is created even with a tool failure. A
Result
object only fails to be created when a tool runs locally and it raises an error. For more information about using the result object, see
Using tools in
Python
.