Manejo de errores con Python
Los errores ocurren. Escribir secuencias de comandos que contemplen y manejen errores puede ahorrarle mucho 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 fallar por muchas otras razones que no se relacionan específicamente con una herramienta de geoprocesamiento; estas razones también se deben determinar y solucionar de una forma apropiada. 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 un error de sistema, o una excepción. Python permite escribir una rutina que se ejecuta automáticamente cada vez que se genera un error del sistema. Dentro de esta rutina de manejo de errores, puede recuperar el mensaje de error desde ArcPy y reaccionar consecuentemente. 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.
Los mensajes de error de la herramienta de geoprocesamiento están acompañados de un código de seis dígitos. Estos códigos de Id. se documentaron para proporcionar información adicional sobre su causa y la forma en la que se pueden solucionar.
declaración try-except
Una declaración try-except se puede utilizar para ajustar programas completos o solamente partes determinadas de códigos para capturar e identificar errores. Si ocurre 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 simple es la forma más básica para manejar errores.
En el siguiente código, Zona de influencia falla porque no se utilizó el parámetro Distancia requerido. En lugar de fallar sin explicación, la declaración except se utiliza para capturar el error, luego recuperar e imprimir el mensaje de error generado por Zona de influencia. Tenga en cuenta que el bloque de excepción solamente se ejecuta si Zona de influencia devuelve un error.
import arcpy try: # Execute the Buffer tool # arcpy.Buffer_analysis("c:/transport/roads.shp", "c:/transport/roads_buffer.shp") except Exception as e: print e.message # 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.message)
La declaración try tiene una cláusula finally opcional que se puede utilizar para las tareas que siempre se deben ejecutar, independientemente de que se haya producido una excepción. En el siguiente ejemplo, se vuelve a realizar el check-in de la extensión 3D Analyst en una cláusula finally, lo que asegura que siempre se vuelva a realizar el check-in de la extensión.
class LicenseError(Exception): pass import arcpy from arcpy import env try: if arcpy.CheckExtension("3D") == "Available": arcpy.CheckOutExtension("3D") else: # Raise a custom exception # raise LicenseError 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: print arcpy.GetMessages(2) finally: # Check in the 3D Analyst extension # arcpy.CheckInExtension("3D")
declaración raise
El ejemplo anterior trató el manejo de una excepción que ocurrió en el código; en algunos casos, es posible que sea necesario crear excepciones personalizadas. Se puede utilizar una declaración raise para este propósito. En el siguiente código, se utiliza una declaración raise cuando se identificó que una clase de entidad de entrada no tiene 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 arcpy.env.overwriteOutput = 1 fc = arcpy.GetParameterAsText(0) try: # Check that the input has features # result = arcpy.GetCount_management(fc) if int(result.getOutput(0)) > 0: arcpy.FeatureToPolygon_management(fc, os.path.dirname(fc) + os.sep + "out_poly.shp") else: # Raise custom exception # raise NoFeatures(result) except NoFeatures: # The input has no features # print fc + " has no features." except: # By default any other errors will be caught here # print arcpy.GetMessages(2)
Clase ExecuteError
Cuando una herramienta de geoprocesamiento falla, arroja una clase de excepción ExecuteError. Esto significa que puede dividir los errores en dos grupos, errores de geoprocesamiento (aquellos que arrojan la excepción ExecuteError) y todo lo demás. Después puede manejar los errores de formas diferentes, como se demuestra en el siguiente código:
import arcpy 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: arcpy.AddError("Non-tool error occurred")
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 valioso.
# 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 + "\n" print msgs
Si se utilizó el código anterior y ocurrió un error de la herramienta de geoprocesamiento, tal como una entrada no válida, esto arrojará ExecuteError y se utilizará la primera declaración except. Esta declaración imprimirá los mensajes de error mediante la función GetMessages. Si se utilizó el mismo código, pero ocurrió un tipo de error diferente, se utilizará la segunda declaración except. En lugar de imprimir los mensajes de geoprocesamiento, obtendrá un objeto traceback e imprimirá los mensajes de error de sistema apropiados.
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. El segundo y el tercer ejemplos no se determinan de manera específica y solamente se imprime la información de traceback.
Su código |
Error resultante |
---|---|
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 |
flotante("una cadena de texto") |
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 |