第六章 使用腳本執行地理處理工具 ||| 第八章 數據查詢和選擇
我們在本章介紹以下案例:
- 創建一個自定義地理處理工具
引言
除了能夠訪問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個字符。不管使用哪種方式,參數讀入后,腳本會作為輸入值繼續執行。