Python でのエラー処理
エラーはどうしても起こるものです。エラーを予期して処理するスクリプトを作成することで多くの時間を節約でき、フラストレーションが少なくなります。ツールがエラー メッセージを返すと、ArcPy はシステム エラーまたは例外を生成します。Python では、例外を処理できるさまざまな構造体とメソッドをユーザが提供することができます。当然ながら、スクリプトが失敗する理由としてはジオプロセシング ツールに特に関連しないものも多数あり、これらについても把握して適切な方法で処理する必要があります。次に、Python による例外処理の基本例を示す手法をいくつか説明します。
ツールがエラー メッセージを書き込むと、ArcPy はシステム エラーまたは例外を生成します。Python では、システム エラーが生成されると自動的に実行されるルーチンを作成できます。このエラー処理ルーチン内で、ArcPy からのエラー メッセージを読み取り、状況に応じて対処することができます。スクリプトにエラー処理ルーチンが含まれていない場合、スクリプトは直ちに失敗してしまうので、堅牢性が低下します。エラー処理ルーチンを使用して、これらのエラーに対処し、スクリプトのユーザビリティを向上させてください。
ジオプロセシング ツールのエラー メッセージには 6 桁のコードが付いています。これらの ID コードは文書化されており、その原因と対処法についての追加情報が提供されます。
try-except ステートメント
try-except ステートメントを使用して、プログラム全体またはコードの特定部分のみをラップし、エラーをトラップして識別できます。try ステートメント内でエラーが発生すると例外が起こり、except ステートメント以下のコードが実行されます。単純な except ステートメントの使用は、エラー処理の最も基本的な形です。
次に示すコードでは、必要な Distance パラメータが使用されていないために [バッファ(Buffer)] が失敗します。説明を表示せずに失敗する代わりに、except ステートメントを使用してエラーをトラップし、Buffer から生成されたエラー メッセージを取得して出力しています。except ブロックは、[バッファ(Buffer)] がエラーを返した場合のみ実行されることに注意してください。
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)
try ステートメントでは、オプションで finally 節を使用でき、これは、例外が発生したかどうかに関係なく常に実行される必要のあるタスクに使用できます。次の例では、3D Analyst エクステンションが finally 句でチェックインし戻されており、これにより、このエクステンションは常にチェックインし戻されます。
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")
raise ステートメント
前述の例では、コード内で発生した例外の処理について説明しましたが、場合によってはカスタム例外を作成する必要が生じます。これには raise ステートメントを使用できます。次のコードでは、入力フィーチャクラスにフィーチャが含まれていないと判定されたときに raise ステートメントが使用されます。これは厳密にはエラーではなく条件であり、このコードを使用すれば失敗を防ぐことができます。
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)
ExecuteError クラス
ジオプロセシング ツールにエラーが発生したら、ExecuteError 例外クラスが投げられます。つまり、エラーはジオプロセシングによるエラー(ExecuteError 例外をスローするもの)とそれ以外のエラーの 2 種類にグループ分けできるということです。したがって、以下のコード例に示すように、エラーは異なる方法で処理できます。
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
大規模で複雑なスクリプトでは、エラーが発生した正確な位置を判別することが難しい場合があります。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 + "\n" print msgs
前記のコードを使用して、ジオプロセシング ツールにエラーが発生した場合(入力が無効など)、ExecuteError が発生し、最初の except ステートメントが使用されます。このステートメントは、GetMessages 関数を使用してエラー メッセージを出力します。同じコードを使用して別のタイプのエラーが発生した場合は、2 番目の except ステートメントが使用されます。ジオプロセシング メッセージを出力する代わりに、traceback オブジェクトを取得して、該当するシステム エラー メッセージを出力します。
次の表は、前記のコードに置き換えて 3 つの異なるコード行を挿入した場合に発生すると予測されるエラーを示しています。1 つめはジオプロセシング ツール エラーで、traceback 情報とジオプロセシング エラー メッセージが出力されます。2 つめと 3 つめの例では、エラーは具体的には捕捉されず、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 |