Los errores ocurren. Escribir secuencias de comandos que esperen y gestionen errores puede ahorrarle tiempo y frustración. Cuando una herramienta devuelve un mensaje de error, ArcPy genera un error de sistema o una excepción. En Python, puede proporcionar una variedad de estructuras y métodos que pueden manejar excepciones. Por supuesto, una secuencia de comandos puede generar errores por razones que no están relacionadas con una herramienta de geoprocesamiento. Estos errores también se deben detectar y tratar de un modo adecuado. Las siguientes secciones ofrecen algunas técnicas que presentan los conceptos básicos del manejo de excepciones de Python.
Cuando una herramienta escribe un mensaje de error, ArcPy genera una excepción arcpy.ExecuteError. Python permite escribir una rutina que se ejecuta automáticamente cuando se genera un error del sistema. En esta rutina de tratamiento de los errores, recupere el mensaje de error de ArcPy y actúe en consecuencia. Si una secuencia de comandos no tiene una rutina de manejo de errores, falla inmediatamente, lo que disminuye su solidez. Utilice las rutinas de manejo de errores y mejore la utilidad de una secuencia de comandos.
declaración try-except
Se puede utilizar una declaración try-except para envolver programas completos o solo partes determinadas del código para interceptar e identificar errores. Si se produce un error dentro de la declaración try, se emite una excepción y luego se ejecuta el código de la declaración except. Utilizar una declaración except básica es la forma más básica de tratar los errores.
En el siguiente código, Zona de influencia falla porque no se ha proporcionado el argumento buffer_distance_or_field requerido. En lugar de fallar sin explicación, la declaración except se utiliza para capturar el error. A continuación, se recupera e imprime el mensaje de error generado por Zona de influencia. El bloque except solo se ejecuta si Zona de influencia devuelve un error.
import arcpy
import sys
try:
# 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])
La declaración try tiene una cláusula finally opcional que se puede utilizar para las tareas que siempre se deben ejecutar, independientemente de si se ha producido una excepción o no. En el siguiente ejemplo, se aplica un check-in a la extensión ArcGIS 3D Analyst en la cláusula finally, lo que garantiza que siempre se aplicará un check-in a la extensión.
class LicenseError(Exception):
pass
import arcpy
try:
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")
Declaración raise
El ejemplo anterior trata una excepción que se ha producido en el código. En algunos casos, puede ser necesario crear excepciones personalizadas. Para este propósito, se puede utilizar una declaración raise. En el siguiente código, se utiliza una instrucción raise cuando se identifica una clase de entidad de entrada sin entidades. Esto no es estrictamente un error sino una condición de que el código se puede utilizar para evitar esta situación.
class NoFeatures(Exception):
pass
import arcpy
import os
import sys
arcpy.env.overwriteOutput = True
fc = arcpy.GetParameterAsText(0)
try:
# 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])
Clase ExecuteError
Cuando una herramienta de geoprocesamiento falla, genera una clase de excepción arcpy.ExecuteError, lo que significa que puede dividir los errores en diferentes grupos, errores de geoprocesamiento (los que producen la excepción arcpy.ExecuteError) y otros tipos de excepción. Después puede manejar los errores de formas diferentes, como se demuestra en el siguiente código:
import arcpy
import sys
try:
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
En secuencias de comandos más grandes y complejas, puede resultar difícil determinar la ubicación exacta de un error. Los módulos sys y traceback de Python se pueden utilizar juntos para aislar la ubicación exacta y la causa del error, identificar la causa de un error con más precisión y ahorrar tiempo de depuración.
# Import the required modules
#
import arcpy
import sys
import traceback
arcpy.env.workspace = "C:/Data/myData.gdb"
try:
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/PythonWin
#
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)
Si se utilizara el código anterior y se produjera un error de la herramienta de geoprocesamiento, como una entrada no válida, se generaría arcpy.ExecuteError y se utilizaría la primera declaración except. Esta declaración imprimirá los mensajes de error mediante la función GetMessages. Si se utilizara el mismo código pero se produjera un tipo diferente de error, se utilizaría la segunda declaración except. En lugar de imprimir mensajes de geoprocesamiento, obtiene un objeto traceback e imprime los mensajes de error correspondientes del sistema.
La siguiente tabla muestra los errores esperados que son el resultado de tres líneas diferentes de códigos que se pueden sustituir en el código anterior. El primero es un error de la herramienta de geoprocesamiento, que imprime la información de traceback y los mensajes de error de geoprocesamiento. Los ejemplos segundo y tercero no se determinan de manera específica y solamente se imprime la información de traceback.
Su código | Error resultante |
---|---|
arcpy.GetCount_management("") |
|
x = "a" + 1 |
|
float("a text string") |
|
Obtener mensajes de error desde un objeto de resultados
A continuación se muestra un breve análisis sobre el objeto Result:
result = arcpy.GetCount_management("c:/data/rivers.shp")
Si la llamada a GetCount_management genera una excepción, el objeto Result no se crea. Esto significa que no puede recuperar mensajes de error desde el objeto Result.
import arcpy
try:
result = arcpy.GetCount_management("c:/data/rivers.shp")
# Return Geoprocessing specific errors
# (this method is incorrect!)
except arcpy.ExecuteError:
arcpy.AddError(result.getMessages(2))
El código anterior falla con el mensaje name 'result' is not defined. Esto se debe a que no se pudo crear el objeto Result por el error de la herramienta. Como no se ha creado el objeto Result, se muestra un error de Python cuando se intenta utilizar el método getMessages.