自定义脚本工具行为

首先进行验证,然后单击该工具的确定按钮。 创建自己的自定义工具时,可通过验证自定义参数与值相互响应交互的方式。 使用用于控制工具行为的 Python 代码块执行验证。

要了解有关验证的详细信息,请参阅了解脚本工具中的验证

您可为脚本工具对话框提供自定义行为,如启用和禁用参数、提供默认值和更新字符串关键字等。 要为脚本工具添加自定义行为,请右键单击脚本工具,单击属性,然后单击验证选项卡。 在验证面板上,您可提供实现名为 ToolValidatorPython 类的 Python 代码。

ToolValidator 是包含以下四种方法的 Python 类:initializeParametersisLicensedupdateParametersupdateMessages。 它还包含标准的 Python 类初始化方法 __init__。 要查看和编辑 ToolValidator 类,请右键单击脚本工具,单击属性,然后单击验证。 以下代码示例显示了默认的 ToolValidator 类代码。 可在原位编辑 Python 代码,或单击在脚本编辑器中打开按钮来编辑代码。

默认 ToolValidator 类和方法
import arcpy

class ToolValidator(object):
    """Class for validating a tool's parameter values and controlling
    the behavior of the tool's dialog."""

    def __init__(self):
        """Setup arcpy and the list of tool parameters.""" 
        self.params = arcpy.GetParameterInfo()

    def initializeParameters(self): 
        """Refine the properties of a tool's parameters. This method is 
        called when the tool is opened."""

    def isLicensed(self):
        """Set whether tool is licensed to execute."""
        return True

    def updateParameters(self):
        """Modify the values and properties of parameters before internal
        validation is performed. This method is called whenever a parameter
        has been changed."""

    def updateMessages(self):
        """Modify the messages created by internal validation for each tool
        parameter. This method is called after internal validation."""

方法描述

__init__

初始化 ToolValidator 类。 导入所需的任何库并初始化对象 (self)。

initializeParameters

优化工具参数属性。 第一次打开工具对话框或在 Python 中执行工具时调用。

isLicensed

设置工具是否获得了执行许可。 第一次打开工具对话框或在 Python 中执行工具时调用。

updateParameters

在用户每次在工具对话框中更改参数时调用。 从 updateParameters 返回后,地理处理将调用它的内部验证例程。

updateMessages

在从内部验证例程返回后调用。 可以检查根据内部验证创建的消息,并根据需要对其进行更改。

ToolValidator 方法概览
注:

避免使用耗时任务,例如地理处理工具或通过验证代码打开数据集,因为每次在工具对话框中进行更改时都会执行 ToolValidator 类。 请使用您脚本中的地理处理工具,而不要使用 ToolValidator 中的地理处理工具。

以下是 ToolValidator 代码的一些示例。 有关所有方法和更多示例的说明,请参阅编写 ToolValidator 类

启用或禁用参数

本例取自热点分析工具:

    def updateParameters(self):
        # If the option to use a weights file is selected (the user chose
        #  "Get Spatial Weights From File"), enable the parameter for specifying 
        #  the file, otherwise disable it
        if self.params[3].value == "Get Spatial Weights From File":
            self.params[8].enabled = True
        else:
            self.params[8].enabled = False

设置默认值

本例也取自热点分析工具:

    def updateParameters(self):
        # Set the default distance threshold to 1/100 of the larger of the width
        #  or height of the extent of the input features.  Do not set if there is no 
        #  input dataset yet, or the user has set a specific distance (Altered is true).

        if self.params[0].valueAsText:
            if not self.params[6].altered:
                extent = arcpy.Describe(self.params[0]).extent
                if extent.width > extent.height:
                    self.params[6].value = extent.width / 100
                else:
                    self.params[6].value = extent.height / 100

        return

更新过滤器

以下是动态更新包含关键字选择列表的值列表过滤器的一个示例。 如果用户在第二个参数中输入 OLD_FORMAT,则第三个参数将包含 POINTLINEPOLYGON。 如果输入 NEW_FORMAT,则第三个参数将包含其他三个选项。

import arcpy

class ToolValidator:
    def __init__(self): 
        self.params = arcpy.GetParameterInfo()

    def initializeParameters(self):
        return

    def updateParameters(self):
        # Provide default values for "file format type" and 
        #  "feature type in file"
        #
        if not self.params[1].altered:
            self.params[1].value = "OLD_FORMAT"
        if not self.params[2].altered:
            self.params[2].value = "POINT"

        # Update the value list filter of the "feature type in file" parameter 
        #   depending on the type of file (old vs. new format) input
        #
        if self.params[1].value == "OLD_FORMAT":
            self.params[2].filter.list = ["POINT", "LINE", "POLYGON"]
        elif self.params[1].value == "NEW_FORMAT":
            self.params[2].filter.list = ["POINT", "LINE", "POLYGON",
                                          "POINT_WITH_ANNO",
                                          "LINE_WITH_ANNO",
                                          "POLYGON_WITH_ANNO"]

        return

    def updateMessages(self):
        return

以下是另一个示例,其中,第二个参数中的值列表过滤器会根据第一个参数中的形状类型“要素类”发生变化:

    def updateParameters(self):
        # Update the value list filter in the second parameter based on the 
        #   shape type in the first parameter
        stringFilter = self.params[1].filter

        if self.params[0].valueAsText:
            shapetype = arcpy.Describe(self.params[0]).shapeType.lower()
            if shapetype == "point" or shapetype == "multipoint":
                stringFilter.list = ["RED", "GREEN", "BLUE"]
            elif shapetype == "polygon":
                stringFilter.list = ["WHITE", "GRAY", "BLACK"]
            else:
                stringFilter.list = ["ORANGE", "INDIGO", "VIOLET"]
        else:
            stringFilter.list = ["RED", "GREEN", "BLUE"]

        # If the user hasn't changed the keyword value, set it to the default value
        #  (first value in the value list filter).
        if not self.params[1].altered:
            self.params[1].value = stringFilter.list[0]
        
        return

自定义消息

    def updateMessages(self):
        self.params[6].clearMessage()

        # Check to see if the threshold distance contains a value of zero and the user has
        #  specified a fixed distance band.
        if self.params[6].value <= 0:
            if self.params[3].value == "Fixed Distance Band":
                self.params[6].setErrorMessage("Zero or a negative distance is invalid \
                                                when using a fixed distance band. Please \
                                                use a positive value greater than zero." )
        elif self.params[6].value < 0:
            self.params[6].setErrorMessage("A positive distance value is required \
                                            when using a fixed distance band. \
                                            Please specify a distance.")

        return

使用方案对象更新输出数据的描述

除了定义工具对话框的行为之外,还可以使用工具验证为 模型构建器 更新输出数据变量的描述。 您可以简单地将 模型构建器 中的数据变量想像成数据集的简要描述。 数据变量包含磁盘上的数据的描述,包括名称、字段、范围和可以使用 Describe 函数描述的其他数据特征等信息。

要在 模型构建器 中使用,所有工具都应当更新它们的输出数据描述。 通过更新描述,模型构建器 中的后续进程可以在任何进程运行之前了解到要对数据进行的待决更改。 以下两个示例显示了后续进程如何查看待决更改。

例如,当在 模型构建器 中使用添加字段工具后,系统会更新“添加字段”工具的输出数据变量以包含新的字段,由此需要标识字段名称的后续工具(例如计算字段)就可以看到所需字段名称并将其用于需要它的参数中。

ToolValidator 类中,您可以使用 Schema 对象设置为输出提供描述的规则;例如,您可以设置以下规则:

  • 创建输入数据集描述的副本,然后将新字段添加到字段列表(如添加字段),或者添加固定字段的列表(如添加 XY 坐标)。
  • 将输出字段的列表设置为数据集集合中的所有字段,或者,添加字段以包含数据集集合(如联合相交)中的要素 ID。
  • 将范围设置为另一个参数中的数据集的范围,或者设置为参数列表中数据集的联合或相交(如裁剪)。
  • 设置特定的几何类型(点、线、面),或将其设置为其他参数中数据集的几何类型,或设置为参数列表中的最小类型或最大类型。 最小和最大几何类型的定义为:点 = 0,折线 = 1,面 = 2。因此,集合 {点, 折线, 面} 中的最小几何类型是点,最大几何类型是面。

输出参数具有方案

Schema 对象通过地理处理进行创建。 类型为要素类、表、栅格或工作空间的每个输出参数都具有 Schema 对象。 仅要素类、表、栅格和工作空间输出数据类型具有方案,其他数据类型不具有方案。 您可以通过 Parameter 对象访问此方案并为描述输出设置规则。 从 updateParameters 返回时,内部验证例程会检查您设置的规则并更新输出的描述。

设置依从关系

无论何时创建规则(如复制参数 3 中数据集的字段,然后添加字段),您都必须告知 Schema 对象要从哪个参数进行复制(参数 3)。 通过向 Parameter 对象添加依从关系可以完成操作。 可添加多个依从关系。

    def initializeParameters(self):
        # Set the dependencies for the output and its schema properties
        self.params[2].parameterDependencies = [0, 1]

parameterDependencies 使用列表。

以下示例显示了依从关系的设置和使用。

设置依从关系示例:裁剪和添加字段

回想一下,通过裁剪工具可以创建输入要素定义的副本,然后将范围设置为输入要素和裁剪要素的交点。 以下提供了如何在 ToolValidator 中实施此规则的示例。 因为裁剪是一个内置工具而非脚本,因此它不使用 ToolValidator 类。 内置工具通过使用原理上与 ToolValidator 相同的内部例程来执行各自的验证操作。 但是,如果它确实使用了 ToolValidator 类,则其外观为:

    def initializeParameters(self):
        # Set the dependencies for the output and its schema properties
        self.params[2].parameterDependencies = [0, 1]

        # Feature type, geometry type, and fields all come from the first 
        # dependent (parameter 0), the input features
        self.params[2].schema.featureTypeRule = "FirstDependency"
        self.params[2].schema.geometryTypeRule = "FirstDependency"
        self.params[2].schema.fieldsRule = "FirstDependency"
    
        # The extent of the output is the intersection of the input features and 
        # the clip features (parameter 1)
        self.params[2].schema.extentRule = "Intersection"

        return

    def updateParameters(self):
        return

添加字段可复制输入参数的定义并添加用户指定的字段。 以下链接介绍了如何在 ToolValidator 中实现添加字段

在 initializeParameters 与 updateParameters 中设置方案

请注意,上述裁剪示例对 initializeParameters 中的 Schema 对象进行了修改,但 updateParameters 只进行返回操作。 另一方面,添加字段必须对 updateParameters 中的 Schema 对象进行修改,因为它在用户提供信息(以及调用 updateParameters)之前没有要添加的字段定义。

您可以将上述两种情况视为静态与动态。 裁剪只依赖在依存参数中找到的数据集(静态行为),但添加字段需要检查字段名称和字段类型等其他非依存参数(动态行为)。

此静态和动态行为在调用 ToolValidator 类的方式上较为明显,例如:

  1. 在首次打开工具对话框时,调用 initializeParameters。 您为描述输出设置静态规则。 此时不会创建任何输出描述,因为用户尚未指定任何参数的值。
  2. 无论用户以何种方式与工具对话框进行交互,都会调用 updateParameters
  3. 考虑到无法根据参数依存关系确定的动态行为(如使用添加字段来添加新字段),updateParameters 可以对方案进行修改。
  4. updateParameters 获得返回值后,会调用内部验证例程并通过应用 Schema 对象中的规则来更新输出数据的描述。
  5. 然后调用 updateMessages。 您可检查内部验证可能已创建的警告消息和错误消息,然后修改它们或者添加警告和错误。

输出数据集名称:克隆派生输出与所需输出

Schema.clone 属性设置为 true 时,您在指示地理处理为参数依存关系列表中的第一个依存参数中的描述创建精确副本(克隆)。 通常,您只需在 initializeParameters 中将 clone 设置为 true 即可,无需在 updateParameters 中进行设置,因为只需要设置一次。

如果输出参数的 ParameterType 被设置为 Derived,则会创建精确副本。 这是添加字段工具的行为。

如果 ParameterType 被设置为 Required,仍会创建精确复本,但会更改数据集的目录路径。 由于大多数工具都会创建数据,因此这是最为常见的行为。

了解更多信息

编写 ToolValidator 类提供了有关 ParameterSchemaFilter 对象的详细信息并给出了代码示例。

基于脚本的所有系统工具(如多环缓冲区)都具有可供您检查和学习的 ToolValidator 代码。 空间统计工作箱中的许多工具都是脚本工具,并具有可供您检查的 ToolValidator 实现。

相关主题