自定义脚本工具行为
验证是单击工具的确定按钮之前要做的全部工作。创建自己的自定义工具时,可通过验证自定义参数与值相互响应交互的方式。通过一个用于控制工具行为的 Python 代码块执行验证。
要了解有关验证的详细信息,请参阅了解脚本工具中的验证
您可以为脚本工具对话框提供自定义行为,如启用和禁用参数、提供默认值和更新字符串关键字等。要为脚本工具添加自定义行为,请右键单击脚本工具,单击属性,然后单击验证选项卡。在“验证”面板上,您可以提供用于实现名为 ToolValidator 的 Python 类的 Python 代码。
尽管 ToolValidator 类是使用 Python 代码实现的,但您仍可使用任一脚本语言来执行工具的实际作业。
ToolValidator 是包含以下三种方法的 Python 类:initializeParameters(self)、updateParameters(self) 和 updateMessages(self)。它还包含标准的 Python 类初始化方法 __init__(self)。要查看和编辑 ToolValidator 类,请右键单击脚本工具,单击属性,然后单击验证选项卡。下图显示了包含默认 ToolValidator 类代码的验证选项卡。单击编辑按钮对代码进行编辑;编辑过程结束后,单击确定或应用以应用编辑内容。
方法 |
描述 |
---|---|
__init__ |
初始化 ToolValidator 类。导入所需的任何库并初始化对象(用户执行)。 |
initializeParameters |
第一次打开工具对话框或第一次在命令行中使用工具时调用。 |
updateParameters |
在用户每次在工具对话框中更改参数时调用。从 updateParameters 返回后,地理处理将调用它的内部验证例程。 |
updateMessages |
在从内部验证例程返回后调用。您可以检查在内部验证过程中创建的消息并根据需要进行更改。 |
请不要在 ToolValidator 中调用其他地理处理工具或打开数据集,因为用户每次在工具对话框中更改内容时都会执行 ToolValidator 类。请使用您的脚本中的地理处理工具,而不要使用 ToolValidator 中的地理处理工具。
您必须实现这三种方法:initializeParameters(self)、updateParameters(self) 和 updateMessages(self)。它们除了执行返回操作之外不必执行任何操作,但必须为 ToolValidator 提供这三种方法,这样 ToolValidator 才能成为有效的 Python 类。
以下是 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 = 1
else:
self.params[8].enabled = 0
编码注释:设置已启用等布尔型变量时,可以使用以下语法:
self.params[8].enabled = 1
self.params[8].enabled = bool(1)
self.params[8].enabled = True # Note upper case: "True", not "true"
将任何非零数字或值都视为真。
设置默认值
本例也取自热点分析工具:
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].value:
if not self.params[6].altered:
extent = arcpy.Describe(self.params[0].value).extent
if extent.width > extent.height:
self.params[6].value = extent.width / 100
else:
self.params[6].value = extent.height / 100
return
更新过滤器
以下是动态更新包含关键字选择列表的值列表过滤器的一个示例。如果用户在第二个参数中输入“OLD_FORMAT”,则第三个参数包含“POINT”、“LINE”和“POLYGON”。如果输入“NEW_FORMAT”,则第三个参数将包含其他三个选项。
class ToolValidator:
def __init__(self):
import arcpy
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
fc = self.params[0].value
if fc:
shapetype = arcpy.Describe(fc).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
使用方案对象更新输出数据的描述
除了定义工具对话框的行为之外,还可以使用 ToolValidator 为模型构建器更新输出数据变量的描述。您可以简单地将模型构建器中的数据变量想像成数据集的简要描述,如下图所示。数据变量包含您使用 Python 中的描述功能访问到的每个属性。
要在模型构建器中使用,所有工具都应当更新它们的输出数据描述。通过更新描述,模型构建器中的后续进程可以在任何进程运行之前了解到要对数据进行的待决更改。以下两个示例显示了后续进程如何了解待决更改。
如下所示的第一个示例显示了一个包含添加字段工具和计算字段工具的模型。在添加字段中,输出数据变量 Parks (2) 被更新为包含新字段 TrackingID。由于输出被更新,因此计算字段对话框会在字段名称的列表中显示 TrackingID。
第二个示例是(未加图示)裁剪工具的输出被用作面转栅格工具的输入模型。由于裁剪工具使用模具方法来创建输入要素,因此,除了一个明显的特例地理范围之外,输出要素类具有的属性与输入要素类具有的属性完全相同。输出要素类的地理范围是输入要素范围和裁剪要素范围的几何交点。面转栅格工具使用新的地理范围来确定默认像元大小。
在 ToolValidator 类中,您可以使用方案对象为构建输出的描述设置规则。例如,您可以按如下方式设置规则:
- 创建输入数据集描述的副本,然后将新字段添加到字段的列表(如添加字段),或者添加固定字段的列表(如添加 XY 坐标)。
- 将输出字段的列表设置为数据集集合中的所有字段,或者,添加字段以包含数据集集合(如联合和相交)中的要素 ID。
- 将范围设置为另一个参数中的数据集的范围,或者设置为参数列表中数据集的联合或相交(如裁剪)。
- 设置特定的几何类型(点、线、面),或将其设置为其他参数中数据集的几何类型,或设置为参数列表中的最小类型或最大类型。最小和最大几何类型的定义为:点 = 0,折线 = 1,面 = 2。因此,集合 {点, 折线, 面} 中的最小几何是点,最大几何是面。
输出参数具有方案
方案对象是由地理处理为您创建的。每个类型为要素类、表、栅格或工作空间的输出参数都具有方案对象。仅要素类、表、栅格和工作空间输出数据类型具有方案,其他数据类型不具有方案。您可以通过参数对象访问此方案并为描述输出设置规则。从 updateParameters 返回时,内部验证例程会检查您设置的规则并更新输出的描述。
设置依从关系
无论何时创建规则(如“复制参数 3 中数据集的字段,然后添加字段”),您都必须告知方案对象要从哪个参数进行复制(参数 3)。通过向参数对象添加依从关系可以完成操作。可添加多个依从关系。
def initializeParameters(self):
# Set the dependencies for the output and its schema properties
#
self.params[2].parameterDependencies = [0, 1]
parameterDependencies 采用 Python 列表。
以下示例显示了依从关系的设置和使用。
设置依从关系示例:裁剪和添加字段
通过取消该裁剪来创建输入要素定义的副本,然后将范围设置为输入要素和裁剪要素的交点。以下示例介绍了如何在 ToolValidator 中实现此规则。(因为裁剪是一个内置工具而非脚本,因此它不使用 Python ToolValidator 类。内置工具通过使用原理上与 ToolValidator 相同的内部例程来执行各自的验证操作。但是,如果系统功能确实使用了 Python 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 中的方案对象进行了修改,但 updateParameters 只进行返回操作。另一方面,添加字段必须对 updateParameters 中的方案对象进行修改,因为它在用户提供信息(以及调用 updateParameters)之前不具有要添加的字段定义。
您可以将上述两种情况视为静态与动态。裁剪只依赖在依存参数中找到的数据集(静态行为),但添加字段需要检查字段名称和字段类型等其他非依存参数(动态行为)。
此静态和动态行为在调用 ToolValidator 类的方式上较为明显,例如:
- 在首次打开工具对话框时,调用 initializeParameters。您为描述输出设置静态规则。此时不会创建任何输出描述,因为用户尚未指定任何参数的值。
- 无论用户以何种方式与工具对话框进行交互,都会调用 updateParameters。
- 考虑到无法根据参数依存关系确定的动态行为(如使用添加字段类添加新字段),updateParameters可以对方案进行修改。
- 从 updateParameters 获得返回值以后,会调用内部验证例程并通过应用方案对象中的规则来更新输出数据的描述。
- 然后会调用 updateMessages。您可检查内部验证可能已创建的警告消息和错误消息,然后修改它们或者添加警告和错误。
输出数据集名称:克隆派生输出与所需输出
将 Schema.Clone 属性设置为真时,您在指示地理处理为参数依存关系列表中的第一个依存参数中的描述创建精确副本(克隆)。通常,您会在 initializeParameters 中而非 updateParameters 中将“克隆”设置为真,因为它只需被设置一次。
如果输出参数的 ParameterType 被设置为 Derived,则会创建精确副本。这是添加字段工具的行为。
如果 ParameterType 被设置为 Required,仍会创建精确复本,但会更改数据集的目录路径。由于大多数工具都会创建新数据,因此这是最常见的行为。
了解更多信息
编写 ToolValidator 类提供了有关参数、方案和过滤器对象的详细信息并给出了代码示例。
基于脚本的所有系统工具(如多环缓冲区)都具有可供您检查和学习的 ToolValidator 代码。空间统计工具箱中的许多工具都是脚本工具并具有可供您检查的 ToolValidator 实现。
但是,您会在 ToolValidator 实现过程中出错(语法、运行时或逻辑错误)。调试 ToolValidator 类向您说明了地理处理如何捕捉和报告错误并为您提供用于调试的一些策略。