调试 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()