錯誤總是在所難免。編寫可預見和處理錯誤的腳本可讓您節省大量時間,同時避免很多令人頭疼的問題。當工具返回錯誤消息時,ArcPy 會生成系統錯誤或異常。在 Python 中,您能夠提供多種可用於處理異常的結構和方法。當然,也會由於其他與地理處理工具不相關的原因導致腳本失敗。同時需要以適當的方式發現和處理這些問題。以下部分會提供一些方法,這些方法介紹了 Python 異常處理的基礎知識。
當工具發出錯誤消息時,ArcPy 會生成 arcpy.ExecuteError 異常。Python 允許您編寫可在生成系統錯誤時立即自動運行的例程。在此錯誤處理例程中,可從 ArcPy 檢索錯誤消息並作出相應的反應。如果腳本沒有錯誤處理例程,則會立即失敗,這就會降低它的穩定性。可使用錯誤處理例程來管理錯誤並提高腳本的可用性。
地理處理工具錯誤消息帶有六位代碼。這些 ID 代碼已記錄在案,可提供有關這些消息產生原因及處理方式的附加信息。
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 extension 通過 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
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
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
float("a text string")
Error Info:
invalid literal for float(): a text string
從結果對象獲取錯誤消息
有關 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 錯誤。
註:
即使在工具失敗的情況下,也會創建通過調用 ArcGIS Server 上的地理處理服務所創建的 Result 對象。僅當工具在本地運行且引發錯誤時,創建 Result 對象才會失敗。有關使用結果對象的詳細信息,請參閱在 Python 中使用工具。
文章授權轉載:gisoracle