Обработка ошибок с помощью Python

Ошибки случаются. Написание скриптов, которое предполагает наличие и обработку ошибок, сохраняет массу времени и ваших сил. Когда инструмент выводит сообщение об ошибке, ArcPy генерирует системную ошибку или исключение. В Python вы можете обеспечить различные структуры и методы для обработки исключений. Конечно, скрипт может не выполниться по причинам, не связанным с инструментом геообработки. Их также следует обнаружить и решить. В следующих разделах предлагаются несколько методов, которые знакомят вас с основами обработки исключений в Python.

Когда инструмент записывает сообщение об ошибке, ArcPy создает исключение arcpy.ExecuteError. Python позволяет написать модуль, который будет запускаться автоматически при возникновении системной ошибки. С помощью этого модуля для обработки ошибок вы сможете получать сообщения об ошибках от ArcPy и реагировать на них. Если скрипт не имеет модуля для обработки ошибок, он завершает выполнение немедленно, что уменьшает его надежность. Модуль обработки ошибок можно использовать для управления ошибками и повышения надежности скриптов.

Сообщения об ошибках в инструментах геообработки обычно имеют шестизначный код. Эти коды-идентификаторы занесены в документы, содержащие дополнительные сведения об их причинах и необходимых действиях.

Выражение try-except

Выражение try-except может быть использовано для разделения программы на шаги, чтобы контролировать выполнение каждого из них и определять места возникновения ошибок. Если ошибка случается внутри выражения try, вызывается исключение и выполняется код в выражении except. Использование выражения except является наиболее простой формой обработки ошибок.

В следующем коде Буфер прекращает работу из-за того, что не был указан обязательный параметр buffer_distance_or_field. Вместо завершения без объяснения причин, выражение except используется для поиска ошибки, ее перехвата и вывода сообщения об ошибке, созданной инструментом Буфер. Обратите внимание, что блок except выполняется только в случае, если в инструменте Буфер происходит ошибка.

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

Выражение try содержит дополнительный оператор finally, использующийся для задач, которые должны выполняться в любом случае, вне зависимости от появления исключения. В следующем примере дополнительный модуль ArcGIS 3D Analyst включается в оператор finally, что обеспечивает постоянное включение модуля.

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

Выражение raise

Предыдущий пример иллюстрирует ошибку в исключении, которое возникло в коде В некоторых случаях может потребоваться создать пользовательские исключения. Для этой цели может быть использовано выражение raise. В следующем коде, выражение raise используется, когда входной класс пространственных объектов определяется как не содержащий объектов. Это не обязательно ошибка, но условие, при котором код может быть использован.

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

Класс ExecuteError

Если выполнение инструмента геообработки прерывается, то появляется класс исключений arcpy.ExecuteError, это означает, что вы можете разделить ошибки на различные группы, ошибки геообработки (они вызывают исключение arcpy.ExecuteError) и другие типы ошибок. Затем можно обрабатывать эти ошибки по разному, как показано в следующем коде:

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

В больших и более сложных скриптах бывает сложно точное определить место возникновения ошибки. Модули Python sys и traceback могут быть использованы вместе для определения точного расположения и причины появления ошибки, определения самой ошибки более точным образом и экономят время при отладке скрипта.

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

Если вышеуказанный код будет использован, и в нем возникнет ошибка геообработки, такая как некорректные входные данные, это вызовет arcpy.ExecuteError, и будет использовано первое выражение except. Это выражение выведет сообщение об ошибке с помощью функции GetMessages. Если в коде возникнет ошибка другого типа, будет использовано второе выражение except. Вместо вывода сообщения о процессе геообработки, будет получен объект traceback и выведено подходящее сообщение о соответствующей системной ошибке.

В таблице ниже показаны ожидаемые ошибки, являющиеся результатом трех различных строк кода, который мог быть использован вместо вышеуказанного кода. Первый пример – ошибка инструмента геообработки, которая генерирует информацию traceback и сообщения об ошибках геообработки. Второй и третий примеры не обрабатываются, а происходит только генерация данных traceback.

Ваш кодРезультирующая ошибка

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

Результаты ошибки

Получение сообщений об ошибках от объекта Result

Краткая информация об объекте Result, показанном ниже:

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

Если при вызове GetCount_management выдается исключение, объект Result не создается. Это означает, что вы не сможете получать сообщения об ошибках от объекта 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))

Выполнение представленного выше кода прерывается с сообщением name 'result' is not defined. Это связано с тем, что объект Result не создается из-за ошибки инструмента. Поскольку объект Result не создается, при попытке использования метода getMessages возникает ошибка Python.

Примечание:

Объект Result, создаваемый посредством службы геообработки в ArcGIS Server, создается даже при ошибке инструмента. Объект Result не создается только тогда, когда инструмент запускается локально и выдает ошибку. Более подробную информацию об использовании объекта result смотрите в разделе Использование инструментов в Python.