调试 ToolValidator 类
如下图所示,要编写 ToolValidator 类,右键单击您的工具,单击属性,再单击验证选项卡,然后单击编辑。这会打开已安装的 Python 编辑器,例如 IDLE 或 PythonWin。添加代码,保存更改,退出编辑器,然后单击“验证”面板上的应用或确定。
单击应用或确定后,会检查您的 ToolValidator 代码是否存在语法错误。如果某类方法中存在语法错误,则会弹出包含语法错误描述的消息框,必须先修复错误才能应用编辑内容。除了检查语法错误之外,还会初始化 ToolValidator 类,并且调用 initializeParameters 方法并检查是否存在运行时错误。运行时错误示例 - 调用了不存在的方法,例如:
fc = self.params[0].Value # Should be "value"
在打开工具对话框并调用 updateParameters 和 updateMessages 方法时,会出现运行时错误。运行时错误以错误的形式在第一个参数中显示。下图对此进行了说明;updateParameters 方法包含拼写错误(例如,value 写成 Value):
要执行该工具,需要编辑 ToolValidator 代码并修复错误(在本例中,将 Value 更改为 value)。
使用 Describe 函数
使用 Describe 函数涉及一个微小但却重要的问题。
使用 Describe 函数时,切勿使用字符串表示值。
不正确(使用了 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 类无语法错误和运行时错误,仍可能具有逻辑错误,例如未合理地启用或禁用参数、未正确计算默认值或未正确填充输出描述等。通常,有两种技术可用于查找脚本工具中的逻辑错误:
- 使用打印指令或地理处理中的 AddMessage 函数打印出自己的调试消息。
- 在调试程序中逐条查看代码。
由于 ToolValidator 代码与工具一同存储且仅在使用对话框或命令行时执行,因此在 ToolValidator 中这两种方法需要进行特殊处理。
显示调试消息
很遗憾,在 ToolValidator 中无法打印消息,即 Python 打印指令无效,因为没有任何位置可写入消息。使用参数对象方法 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 包含工具的名称而不是标注。这样使得地理处理可以创建参数数组。然后在数组中设置一个或多个参数。
现在添加 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()