第六章 使用脚本执行地理处理工具 ||| 第八章 数据查询和选择
我们在本章介绍以下案例:
- 创建一个自定义地理处理工具
引言
除了能够访问ArcGIS提供的系统工具,我们还可以创建自己的自定义工具。这些工具跟系统工具的工作模式相同,也可以在模型构造器,Python窗口以及独立的Python脚本中使用。许多组织机构都会创建自定义工具集来专门处理自己的数据。
创建一个自定义地理处理工具
除了能够在脚本中执行所有可用的工具,你还可以在脚本中调用自己创建的自定义工具。许多自定义工具来专门用于执行组织机构内特定需求的地理处理任务。而且这些工具也很方便共享。
Getting ready
在本案例中,你将学习如何将脚本添加到ArcToolbox下的自定义工具箱中创建自定义地理处理脚本工具。创建自定义脚本工具有很多优点。创建完成后,脚本就变成了地理处理框架中的一部分,也就意味着该脚本可以在模型中,命令行或者其他脚本中使用。另外,脚本也就可以获取ArcMap的环境设置以及帮助文档。同时自定义脚本工具能够提供一个简单易用的用户界面以及容错机制(error-prevention capabilities)。容错机制会提供一个对话框来通知用户工具运行中出现的错误。
ArcToolbox提供的系统工具箱是只读的,不能接受新的工具,因此这些自主开发的脚本工具只能添加到自定义工具箱中。在本案例中,你将会使用一个已编写好的Python脚本,该脚本会从一个逗号分隔符文本文件(comma-delimited text file)中读取野外火情数据,之后将数据转为一个FireIncidents
的点要素文件。脚本中需要引用的数据集路径已经过硬编码处理,你需要修改脚本能够接受动态变量的输入。之后将修改后的脚本添加到ArcToolbox中的一个自定义工具中,该工具会为最终用户提供了一个可视化的界面来执行脚本。
How to do it...
你编写的Python地理处理脚本可以添加到ArcToolbox中的自定义工具箱中。你不能将脚本添加到任何一个系统工具箱中,比如Analysis或Data Management。不过,你可以创建一个新的自定义工具箱来添加脚本。
1.打开ArcMap创建一个空白的地图文档并打开ArcToolbox窗口。
2.右键单击ArcToolbox内的任何空白位置,选择添加工具箱(Add Toolbox)。在Add Toolbox对话框中,点击New Toolbox按钮。系统会创建一个Toolbox.tbx
的工具箱,在下一步中你可以重命名该工具箱:
3.转到C:\ArcpyBook\Ch7
文件夹,在该文件夹下创建一个Wildfire Tools
的工具箱:
4.选中Wildfire Tools.tbx
文件然后点击打开(Open)按钮。如下图所示,该工具箱就出现在ArcToolbox窗口中了:
5.每一个工具箱都需要给定一个名称和别名。别名可以用于唯一识别你的自定义工具。别名应该尽量简短且不包含特殊字符。右键单击新添加的工具箱选择属性(Properties)。如下图所示添加一个wildfire
的别名:
你还可以右键单击工具箱选择新建|工具集(New|Toolset)在工具箱中创建一个新的工具集。工具集可以按照功能来对脚本进行分组。在本案例中,你不需要这么做,不过如果在以后需要对脚本进行分组管理时,你就可以通过创建工具集来完成。
6.接下来,我们需要修改InsertWildfires.py
脚本文件使其能够接受用户通过ArcToolbox界面提供的动态输入参数。在IDLE中打开C:\ArcpyBook\Ch7\InsertWildfires.py
文件。你会看到工作空间路径和包含野火数据的逗号分隔文本文件的路径都是硬编码处理的:
arcpy.env.workspace = "C:/ArcpyBook/data/Wildfires/WildlandFires.mdb"
f=open("C:/ArcpyBook/data/Wildfires/NorthAmericaWildfires_2007275.txt","r")
7.删除以上两行代码。另外,输出要素类名称也是使用硬编码处理:
cur = arcpy.InsertCursor("FireIncidents")
硬编码限制了脚本的灵活性。如果数据集移动或者删除了,脚本也就无法运行。除此以外,硬编码还会让脚本缺少针对不同输入和输出数据集要求的灵活性。在下一步中,我们会移除这些硬编码,让脚本可满足动态输入参数要求。
8.我们会调用arcpy
提供的GetParameterAsText()
函数来接受用户提供的动态输入参数。如下所示,在try
语句下添加以下脚本代码:
try:
outputFC = arcpy.GetParameterAsText(0)
fClassTemplate = arcpy.GetParameterAsText(1)
f = open(arcpy.GetParameterAsText(2),"r")
arcpy.CreateFeatureclass_management(os.path.split(outputFC)[0],os.path.split(outputFC)[1],"point",fClassTemplate)
你会看到我们调用了Data Management工具箱中的CreateFeatureClass
工具,并将outputFC
变量和模板要素类(fClassTemplate
)变量传递给该工具。该工具将会创建一个包含了用户指定的输出要素类的空要素类文件。
9.你还需要修改一行用于创建插入游标(InsertCursor
)对象的代码。如下所示:
cur = arcpy.InsertCursor(outputFC)
10.修改后的完整代码如下:
import arcpy,os
try:
outputFC = arcpy.GetParameterAsText(0)
fClassTemplate = arcpy.GetParameterAsText(1)
f = open(arcpy.GetParameterAsText(2),"r")
arcpy.CreateFeatureclass_management(os.path.split(outputFC)[0],\
os.path.split(outputFC)[1],"point",fClassTemplate)
lstFires = f.readlines()
cur = arcpy.InsertCursor(outputFC)
cntr = 1
for fire in lstFires:
if 'Latitude' in fire:
continue
vals = fire.split(",")
latitude = float(vals[0])
longitude = float(vals[1])
confid = int(vals[2])
pnt = arcpy.Point(longitude,latitude)
feat = cur.newRow()
feat.shape =pnt.shape
feat.setValue("CONFIDENCEVALUE",confid)
cur.insertRow(feat)
arcpy.AddMessage("Record number: " + str(cntr) + "writen to feature class")
cntr = cntr + 1
del feat
del cur
except:
print arcpy.GetMessages()
finally:
f.close()
接下来,我们将脚本添加到刚刚创建的Wildfire Tools工具箱中。
11.在ArcToolbox中,右键单击之前创建的Wildfire Tools工具箱,选择添加|脚本(Add|Script)。如下图所示弹出添加脚本(Add Script)对话框。填写脚本名称,标签以及描述信息。名称(Name)中不能包含空格以及特殊字符。标签(Label)信息为脚本工具的显示名称。本案例中,标签设置为Load Wildfires From Text
文本。最后,添加一些描述信息来说明脚本执行的细节等。
12.名称,标签和描述的细节信息如下图所示:
13.点击下一步(Next)按钮显示添加脚本的下一个对话框。
14.在该对话框中,你需要制定需要添加到工具中的脚本文件。选择InsertWildfires.py
脚本文件。
15.你还需要勾选在进程中运行Python脚本(Run Python Script in process)。在进程中运行脚本会提高脚本执行的速度。
进程外运行Python脚本需要ArcGIS创建一个单独的进程来执行脚本。开启进程和执行脚本的时间会导致脚本运行性能的问题。通常都选择在进程中运行Python脚本。在进程中运行脚本意味着ArcGIS不需要开启第二个进程来运行脚本,脚本与ArcGIS运行在同一个进程中。
16.点击下一步(Next)显示参数窗口,如下图所示:
你在该对话框中输入的每一个参数都要与一个单独的GetParameterAsText()
函数调用相关联。在前面,我们已经修改过脚本使其接受通过GetParameterAsText()
函数获取的动态参数。该对话框中参数的输入的顺序应该与脚本中指定接受的顺序一致。比如,你在脚本中插入了下面的代码:
outputFC = arcpy.GetParameterAsText(0)
那么你在参数对话框中添加的第一个参数就需要与该行代码关联。在脚本中,outputFC
参数代表运行脚本后创建的要素类。你通过点击显示名称(Display Name)下的第一行来添加参数。你可以在该位置输入任意文本,该文本会显示给用户。你还需要选择与该参数相关联的数据类型。在本案例中,数据类型(Data Type)应该选择要素类(Feature Class)。每一个参数都有一些属性可以设置。其中比较重要的属性包括类型(Type),方向(Direction)以及默认值(Default)。
17.如下图所示在对话框中输入输出要素类的信息。确保方向(Direction)属性设置为Output:
18.接下来,我们需要添加一个作为输出要素类属性模板的要素类参数。如下图所示输入信息:
19.最后,我们还需要添加一个指定逗号分隔符文本文件的参数,该文本文件用于创建要素类的输入参数。如下图所示输入信息:
20.点击完成(Finish)按钮。如下图所示,一个新的脚本工具就会添加到Wildfire Tools工具箱中:
21.现在我们来测试工具是否可用。双击脚本工具弹出如下图所示对话框:
22.定义一个输出要素类文件。点击打开文件图标找到C:\ArcpyBook\data\Wildfires
中的WildlandFires.mdb
个人数据库。
23.你还需要指定一个输出要素类的名称。在本案例中,我们将输出要素类命名为TodayWildfires
,当然你可以命名为你喜欢的名称。点击保存(Save)按钮。
24.对于属性模板,你需要指向已经创建好的FireIncidents
要素类。该要素类包含了一个CONFIDENCEVAL
的字段,该字段也会在输出要素类中创建。点击浏览(Browse)按钮,选择C:\ArcpyBook\data\Wildfires\WildlandFires.mdb
中的FireIncidents
要素类文件。点击添加(Add)按钮。
25.最后一个参数需要指向一个包含野外火情数据的逗号分隔符文本文件。点击浏览(Browse)按钮,选择C:\ArcpyBook\data\Wildfires
中的
NorthAmericaWildfire_2007275.txt
文件。点击添加(Add)按钮。
以上参数选择完成后,工具界面如下所示:
26.点击确定(OK)按钮。如下图所示,消息会出现在对话框中。这是一个标准的地理处理工具对话框。如果所有参数设置正确,如下图所示你将看到新的要素类创建完成的提示消息:
如下图所示,新创建的要素类添加到ArcMap显示窗口中:
How it works...
几乎所有的脚本都带有参数,用户需要在工具对话框中提供所需的参数值。工具执行时,参数值传递给脚本。脚本读取这些参数值后在进行处理。Python脚本可以将参数作为输入值。参数可以让脚本接受动态参数值。在这之前,我们所有的脚本都是采用硬编码值。通过指定脚本的输入参数,你就可以在脚本运行时再获取参数值。这一功能让脚本变得更为灵活。
GetParameterAsText()
函数用于获取输入参数值,该函数从零值开始索引参数在参数列表中的位置,即第一个参数占据索引位置0
。每一个后续参数索引值递增加1
。输出要素类是通过读取逗号分隔符文本文件来创建并将其赋值给变量outputFC,该参数通过GetParameterAsText(0)
语句获取。使用语句GetParameterAsText(1)
,我们获取了作为输出要素类属性模板的一个要素类参数。该模板要素类中的字段将会用于定义输出要素类中的字段。最后GetParameterAsText(2)
语句会创建一个变量f
,该变量用于保存要读取的逗号分隔符文本文件。
There's more...
arcpy.GetParameterAsText()
函数并非获取信息传递给脚本的唯一方式。当你从命令行调用Python脚本,你可以传递一组参数(argument)。当向脚本传递参数时,每个参数必须使用空格隔开。这些参数保存在一个基于sys.argv
的列表对象中。使用sys.argv
引用索引值0
来引用列表中的第一个元素,该元素用于保存脚本名称。每一个后续的参数索引值依次递增加1。因此,第一个参数保存在sys.argv[1]
中,第二个参数保存在sys.argv[2]
。这些参数可以通过脚本来获取。
建议大家使用GetParameterAsText()
函数,这是因为前者没有字符数量的限制而后者则要求每个参数要小于1024个字符。不管使用哪种方式,参数读入后,脚本会作为输入值继续执行。