调试 ToolValidator 类

如下图所示,要编写 ToolValidator 类,右键单击您的工具,单击属性,再单击验证选项卡,然后单击编辑。这会打开已安装的 Python 编辑器,例如 IDLE 或 PythonWin。添加代码,保存更改,退出编辑器,然后单击“验证”面板上的应用确定

输入 ToolValidator 代码

单击应用确定后,会检查您的 ToolValidator 代码是否存在语法错误。如果某类方法中存在语法错误,则会弹出包含语法错误描述的消息框,必须先修复错误才能应用编辑内容。除了检查语法错误之外,还会初始化 ToolValidator 类,并且调用 initializeParameters 方法并检查是否存在运行时错误。运行时错误示例 - 调用了不存在的方法,例如:

fc = self.params[0].Value  # Should be "value"

在打开工具对话框并调用 updateParametersupdateMessages 方法时,会出现运行时错误。运行时错误以错误的形式在第一个参数中显示。下图对此进行了说明;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 类无语法错误和运行时错误,仍可能具有逻辑错误,例如未合理地启用或禁用参数、未正确计算默认值或未正确填充输出描述等。通常,有两种技术可用于查找脚本工具中的逻辑错误:

由于 ToolValidator 代码与工具一同存储且仅在使用对话框或命令行时执行,因此在 ToolValidator 中这两种方法需要进行特殊处理。

显示调试消息

很遗憾,在 ToolValidator 中无法打印消息,即 Python 打印指令无效,因为没有任何位置可写入消息。使用参数对象方法 setErrorMessagesetWarningMessage 显示调试消息会出现问题 - 因为只能在 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()

7/10/2012