次の図に示すように、ToolValidator クラスをプログラミングするには、ツールを右クリックして、[プロパティ] をクリックし、[確認] タブをクリックして [編集] をクリックします。これにより、IDLE や PythonWin などのインストール済みの Python エディタが開きます。コードを追加し変更を保存したら、エディタを終了して [確認] パネルの [適用] または [OK] をクリックします。
[適用] または [OK] をクリックすると、入力した ToolValidator コードに構文エラーがないかどうかがチェックされます。クラスのメソッドのいずれかに構文エラーがある場合は、構文エラーの説明を示すメッセージ ボックスが表示されるので、そのエラーを修正するまでは編集を適用できません。構文エラーのチェックに加えて、ToolValidator クラスが初期化され、initializeParameters メソッドが呼び出されて、ランタイム エラーがないかどうかがチェックされます。存在しないメソッドの呼び出しを示すランタイム エラーの例を次に示します。
fc = self.params[0].Value # Should be "value"
ツールのダイアログ ボックスが開かれ updateParameters と updateMessages メソッドが呼び出されたときにこれらの 2 つのメソッドのランタイム エラーが検出されています。ランタイム エラーは最初のパラメータのエラーとして表示されます。次の図に示すように、updateParameters メソッドに入力ミス(Value と value など)があります。
このツールを実行するには、ToolValidator コードを編集して、エラーを修正する(この例では Value を value に変更する)必要があります。
Describe 関数の使用
Describe 関数の使用は、些細なようで大きな問題の 1 つです。
正しくない例(str 関数を使用)
desc = arcpy.Describe(str(self.params[0].value))
正しい例
desc = arcpy.Describe(self.params[0].value)
データセットに文字列表現を使用しないでください(使用した場合、そのデータセットにカタログ パスが生成されます)。これはそのデータセットがディスク上に存在していない場合があるからです(データセットがモデルから導出される変数である場合、そのモデルを先に実行しないと、データセットはディスク上に存在することができません)。(パラメータに導出変数が含まれているかどうかは、parameter.isInputValueDerived メソッドによって確認できます。)データセットの文字列表現を使用した場合は、そのデータセットがまだ存在していない可能性により Describe 関数が失敗することがあります。
テスト前に、パラメータに値が設定されているかどうかを確認
一般的な ToolValidator のコーディングのミスは、初期設定されていない値がないかどうかをテストしないことにあります。
正しくない例(値が設定されていないため arcpy.Describe が失敗)
fc = self.params[0].value
shapetype = arcpy.Describe(fc).shapeType.lower()
正しい例(最初に値の有無をテスト)
fc = self.params[0].value
if fc:
shapetype = arcpy.Describe(fc).shapeType.lower()
高度なデバッグ
作成した ToolValidator クラスに構文エラーやランタイム エラーがない場合でも、パラメータが適切に有効化/無効化されてない、デフォルト値の計算が正しくない、出力の記述が正しく入力されていないなど、ロジック エラーが存在している場合があります。従来、スクリプト ツール内のロジック エラーの検出には次の 2 つの手法が用いられてきました。
- print ディレクティブまたは AddMessage ジオプロセシング関数を使用して独自のデバッグ メッセージを出力する。
- デバッガのコードを順次調べる。
ToolValidator コードはツールとともに格納され、ダイアログまたはコマンド ラインが使用されるときに一度だけ実行されるため、これらの 2 つの手法を使う場合は ToolValidator での特別な処理が必要になります。
デバッグ メッセージの表示
残念ながら ToolValidator では、メッセージを書き込む場所がないことからメッセージを出力できず、Python の print ディレクティブは無効になります。パラメータ オブジェクトのメソッド setErrorMessage と setWarningMessage を使用したデバッグメッセージの表示には問題があります。これらのメソッドは updateMessages メソッドでのみ使用できますが、表示したいデバッグ メッセージは updateParameters で生成されたものである可能性が高く、したがって、ToolValidator のクラスのメソッド間でデバッグ メッセージを受け渡すことは不可能です。
ただし、次の手法を使用することは可能です。
- ツールに新しい文字列パラメータを追加します。これを最後のパラメータにします。
- updateParameters で、デバッグ メッセージをこの新しいパラメータに書き込みます。
- ツールのダイアログ ボックスを開き、値を指定します。デバッグ メッセージがその新しい文字列パラメータで表示されます。
- 問題を見つけ修正したら、この最後のパラメータをパラメータ リストおよび ToolValidator コード内の使用箇所から削除します。
次のコードは、この手法を具体的に示しています。
def updateParameters(self):
if self.params[0].value and not self.params[1].altered:
desc = arcpy.Describe(self.params[0].value)
fields = desc.fields
for field in fields:
fType = field.type.lower()
if fType == "smallinteger" or \
fType == "integer":
self.params[1].value = field.name
# Update our "debug" parameter to show
# the field type
#
self.params[2].value = fType
break
# No field, update "debug" parameter
#
self.params[1].value = ""
self.params[2].value = "No field found"
return
Python IDE でのデバッグ
場合によっては、デバッグ メッセージの出力だけでは十分ではなく、Python IDE(IDLE や PythonWin など)を使用してコードをデバッグし、ブレークポイントの設定、コードの順次確認、値の検査、ロジック エラーの修正を行う必要があります。
デバッグを行うには、スタンドアロン スクリプトを作成してエディタ内でそのスクリプトをデバッグします。スクリプトの最上部では、次に示すように、ツールボックスをロードし、パラメータの配列を作成し、必要なパラメータ値を設定します。
import arcpy
# Load the toolbox and get the tool's parameters, using the tool
# name (not the tool label).
#
arcpy.ImportToolbox("E:/Documents/Tool Validation Examples.tbx")
params = arcpy.GetParameterInfo("HotSpots_stats")
# Set required parameters
#
params[0].value = "D:/st_johns/city.mdb/roads"
arcpy.GetParameterInfo にはラベルではなくツールの名前が含まれていることに注意してください。これによって、ジオプロセシングで独自のパラメータの配列を作成できるようになります。配列には 1 つ以上のパラメータを設定できます。
次に、作成した ToolValidator コードを追加します([プロパティ] ダイアログ ボックスから直接、コードのコピー/貼り付けを行うことができます)。
スクリプトの下部では、次に示すように ToolValidator を呼び出します。
# Create the ToolValidator class and call updateParameters
# and/or updateMessages
#
validator = ToolValidator()
validator.updateParameters()
確認のため、スタンドアロン スクリプトの基本構造を次に示します(実際の ToolValidator コードは、例を簡単にするために削除されています)。
# Create the parameter array and values
#
import arcpy
# Add the toolbox and fetch the parameter list
#
arcpy.ImportToolbox("E:/Documents/Tool Validation Examples.tbx")
params = arcpy.GetParameterInfo("HotSpots_stats")
params[0].value = "D:/st_johns/city.mdb/roads"
# ToolValidator class block
#
class ToolValidator:
def __init__(self):
import arcpy
self.params = arcpy.GetParameterInfo()
def initializeParameters(self):
# (initializeParameters code here)
return
def updateParameters(self):
# (updateParameters code here)
return
def updateMessages(self):
# (updateMessages code here)
return
# Call routine(s) to debug
#
validator = ToolValidator()
validator.updateParameters()
validator.updateMessages()