1. 程式人生 > >淺談使用ArcPy執行大資料量處理任務

淺談使用ArcPy執行大資料量處理任務

Python功能強大而易於學習。對於ArcGIS for Desktop使用者來講,Python是提高工作效率的不二選擇。

Arcpy是esri提供的用於高效資料處理分析、製圖等的Python站點包。 利用ArcPy,我們可以在ArcMap的Python視窗互動執行指令碼,還可以建立自定義指令碼工具或指令碼工具箱,還可以在ArcGIS之外執行獨立指令碼,享受更純正的python體驗。

這一篇說說如何利用Python批量執行資料處理任務,這個問題也是前段時間遇到的使用者的實際問題,比較有價值。

需求

還是從例項開始……

有一個簡單但耗體力的裁剪任務,希望通過大量面分割(逐一裁剪)大量的資料,類似Split工具要完成的任務,並且要按照一定的規則命名將分割結果輸出到指定的位置,例如要求有指定字首。

實現

例如,一種思路是逐一遍歷面要素,然後去裁剪目標資料再輸出,這時你可能會遇到下面的小問題:

我如何通過ArcPy獲取要素的幾何?

在ArcPy中提供了一個數據訪問模組/Data Access (arcpy.da),我們可以通過遊標(Cursor)來查詢要素的幾何或屬性。在這個需求中是逐一遍歷面要素的幾何,我們選擇 SearchCursor,通過 [email protected] 可以訪問要素的幾何。

語法: SearchCursor(in_table, field_names, {where_clause}, {spatial_reference}, {explode_to_points}, {sql_clause})

瞭解詳細的幫助資訊點這裡

那麼可以把函式主體定義成這樣,即可實現需求:

def MyBatchClip(Parameter):
    # 引數
    inputFC = Parameter[0]
    ClipArea = Parameter[1]
    OutputWS = Parameter[2]
    Prefix = Parameter[3]
    # 欄位列表,[email protected] 訪問要素幾何物件
    Fields = ['FID','[email protected]']
    # 遍歷面要素逐一裁剪目標資料並輸出自定義字首的結果。
with arcpy.da.SearchCursor(ClipArea,Fields) as cursor: for row in cursor: outputFC = os.path.join(OutputWS, Prefix+str(row[0])+'.shp') arcpy.Clip_analysis(inputFC, row[1], outputFC)

多程序

如果這個批量任務是大量的,如何更高效地開動起來?

這裡按照esri以前的一篇 Blog 提到的方法分享給大家,使用Multiprocessing模組並行處理。 Multiprocessing 模組是Python的一個標準庫,通過這個庫,我們可以利用多核CPU,來實現多程序處理大資料量的任務。

可以通過 multiprocessing.Pool 來使用程序池,Pool類可以管理固定數目的程序,預設是開啟和機器CPU數目相同的程序。

語法:
multiprocessing.Pool([processes[, initializer[, initargs[, maxtasksperchild]]]])
processes表示pool中程序的數目,預設地為當前CPU的核數。
initializer表示新程序的初始化函式。
initargs表示新程序的初始化函式的引數。
maxtasksperchild表示每個程序執行task的最大數目

把指令碼修改下,加上多程序處理的部分:

# -*- coding:utf-8 -*-
__author__ = 'kikita'

import arcpy
import timeit
import time
import multiprocessing
import os

arcpy.env.workspace =  r'D:\LearnAboutPython\MyPythonProject\UsingCurser\DemoDataS.gdb'
arcpy.env.overwriteOutput = True

# 批量裁剪函式
def MyBatchClip(Parameter):
    # 引數
    inputFC = Parameter[0]
    ClipArea = Parameter[1]
    OutputWS = Parameter[2]
    Prefix = Parameter[3]
    # 欄位列表,其中 [email protected]用於訪問資料幾何
    Fields = ['OBJECTID','[email protected]']
    with arcpy.da.SearchCursor(ClipArea,Fields) as cursor:
        for row in cursor:
            outputFC = os.path.join(OutputWS, Prefix+str(row[0])+'.shp')
            arcpy.Clip_analysis(inputFC, row[1], outputFC)
            print Prefix+str(row[0])+'.shp'


if __name__ == '__main__':
    # 引數
    OutputWS = r'D:\LearnAboutPython\MyPythonProject\UsingCurser\OutputWS'
    # SDE庫輸出
    #OutputWS = r'C:\Connection131.sde'
    Parameter1 = ['CountyPoints','Area_A',OutputWS, 'AAA_']
    Parameter2 = ['hyd_line','Area_B',OutputWS, 'BBB_']
    Parameter3 = ['River_line.shp','Area_C.shp',OutputWS,'CCC_']
    Parameters = [Parameter1,Parameter2,Parameter3 ]
    # 當前CPU核數
    print 'CPU Count:' + str(multiprocessing.cpu_count())
    # 程序池
    MyGPpool = multiprocessing.Pool()
    # 多程序並行處理
    StartTime = time.time()
    results = MyGPpool.map(MyBatchClip,Parameters)
    EndTime = time.time()
    print 'Elapsed:  ' + str(EndTime - StartTime) + '  Seconds...'

結果

CPU Count:8
AAA_0.shp
BBB_0.shp
CCC_0.shp
BBB_1.shp
AAA_1.shp
CCC_1.shp
BBB_2.shp
AAA_2.shp
CCC_2.shp
……
……
……
BBB_28.shp
AAA_27.shp
BBB_29.shp
CCC_28.shp
CCC_29.shp
AAA_28.shp
BBB_30.shp
CCC_30.shp
AAA_29.shp
AAA_30.shp
Elapsed:  28.628000021  Seconds...

一點有用的提示:

1.在使用Multiprocessing時,注意資料鎖定(Schema Lock)的問題,例如這個例子中,當輸出工作空間選擇為FileGDB時出現異常。 使用資料夾輸出 Shapefile,或者以SDE資料庫作為輸出工作空間,都是可以的。

2.我在程式碼中也加入了計時,用於比較並行與否的耗時情況。 但是有時確實會發現,較簡單的處理任務時,多程序並行並不比單程序快,因為匯入模組和啟動程序都需要花時間。

Also available Here.