Gestion des erreurs avec Python

Des erreurs se produisent. Ecrire des scripts qui détectent et gèrent les erreurs peut vous permettre de gagner beaucoup de temps. Lorsqu’un outil renvoie un message d’erreur, ArcPy génère une erreur système ou une exception. Dans Python, vous pouvez fournir différentes structures et méthodes pour gérer les exceptions. Bien entendu, un script peut échouer pour d’autres raisons qui ne sont pas liées à un outil de géotraitement. Ces raisons doivent également être identifiées et gérées de manière appropriée. Les sections suivantes fournissent quelques techniques qui vous présentent les concepts de base de la gestion des exceptions Python.

Lorsqu’un outil écrit un message d’erreur, ArcPy génère une exception arcpy.ExecuteError. Python permet d’écrire une routine qui s’exécute automatiquement lorsqu’une erreur système est générée. Dans cette routine de gestion des erreurs, récupérez le message d’erreur à partir d’ArcPy et réagissez en conséquence. Si un script ne comporte pas de routine de gestion des erreurs, il échoue aussitôt, ce qui réduit son efficacité. Utilisez des routines de gestion d’erreur pour gérer les erreurs et améliorer la fonctionnalité d’un script.

Les messages d’erreur des outils de géotraitement sont accompagnés d’un code à six chiffres. Ces codes d’identification sont documentés pour fournir des informations supplémentaires sur leur cause et la manière dont ils peuvent être gérés.

instruction try/except

Une instruction try-except permet de passer en revue des programmes entiers ou des portions particulières de code afin d’identifier les erreurs. Si une erreur se produit au sein de l’instruction try, une exception est générée et le code placé sous l’instruction except est exécuté. L’utilisation d’une instruction except de base est la façon la plus facile de gérer les erreurs.

Dans le code ci-dessous, l’outil Zone tampon échoue car l’argument buffer_distance_or_field requis n’a pas été spécifié Au lieu d’échouer sans explication, l’instruction except permet d’identifier l’erreur, puis de récupérer et d’imprimer le message d’erreur généré par l’outil Zone tampon. Notez que le bloc except est exécuté uniquement si l’outil Zone tampon renvoie une erreur.

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])

L’instruction try comporte une clause finally facultative utile pour les tâches devant systématiquement être exécutées, qu’une exception se produise ou pas. Dans l’exemple suivant, l’ArcGIS 3D Analyst extension est réinsérée selon une clause finally, ce qui signifie qu’elle est toujours réinsérée.

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")

Instruction raise

L’exemple précédent concerne une exception survenue dans le code. Dans certains cas, vous pouvez être amené à créer des exceptions personnalisées. Une instruction raise peut être utilisée à cette fin. Dans le code suivant, une instruction raise est utilisée quand une classe d’entités en entrée est identifiée comme n’ayant aucune entité. Il ne s’agit pas strictement d’une erreur mais d’une condition contre laquelle le code peut intervenir.

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])

Classe ExecuteError

Lorsqu’un outil de géotraitement échoue également, il lève une classe d’exception arcpy.ExecuteError, ce qui signifie que vous pouvez diviser les erreurs en différents groupes : les erreurs de géotraitement (qui lèvent l’exception arcpy.ExecuteError) et d’autres types d’exceptions. Vous pouvez ensuite gérer les erreurs de manière différente, comme indiqué dans le code ci-dessous :

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

Dans les scripts plus importants et plus complexes, il peut être difficile de déterminer l’emplacement précis d’une erreur. Les modules sys et traceback de Python permettent d’isoler l’emplacement exact et la cause d’une erreur, en identifiant plus précisément la cause de l’erreur et en vous permettant d’économiser un temps précieux pour le débogage.

# 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
    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 le code ci-dessus est utilisé et qu’une erreur d’outil de géotraitement se produit, une entrée incorrecte par exemple, l’erreur arcpy.ExecuteError est levée et la première instruction except est utilisée. Cette instruction imprime les messages d’erreur à l’aide de la fonction GetMessages. Si le même code était utilisé, mais qu’un type d’erreur différent se produisait, la seconde instruction except serait utilisée. Au lieu d’imprimer des messages de géotraitement, elle obtient un objet traceback et imprime les messages d’erreur système appropriés.

Le tableau suivant montre les erreurs attendues qui proviennent de trois lignes de codes différentes qui pourraient être substituées dans le code ci-dessus. La première est une erreur d’outil de géotraitement, qui imprime les informations traceback et les messages d’erreur de géotraitement. Le deuxième et le troisième exemple ne sont pas spécifiquement identifiés et impriment uniquement les informations traceback.

Votre codeErreur

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

Résultats d’erreur

Obtention de messages d’erreur à partir d’un objet Result

Ci-dessous figure une brève présentation de l’objet Result :

result = arcpy.GetCount_management("c:/data/rivers.shp")

Si l’appel de GetCount_management déclenche une exception, l’objet Result n’est pas créé. Cela signifie que vous ne pouvez pas récupérer de messages d’erreur de l’objet 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))

Le code ci-dessus échoue avec le message name 'result' is not defined. Ceci est dû au fait que l’objet Result n’a pas pu être créé en raison de l’échec de l’outil. Comme aucun objet Result n’est créé, une erreur Python est déclenchée lors de la tentative d’utilisation de la méthode getMessages.

Remarque :

Un objet Result créé en appelant un service de géotraitement sur ArcGIS Server est créé même en cas d’échec d’un outil. La création d’un objet Result n’échoue que lorsqu’un outil s’exécute localement et déclenche une erreur. Pour plus d’informations sur l’utilisation de l’objet résultat, reportez-vous à la rubrique Utilisation des outils dans Python.