我正在做一些數字運算與arcpy
光柵並希望使用multiprocessing
包來加快速度。基本上,我需要遍歷元組列表,使用每個元組進行一些柵格計算並將一些輸出寫入文件。我的輸入包括一個數據光柵(測深),限定區域的光柵,和兩個浮體(水錶面高度,深度)的元組的。我的程序由一個函數computeplane
組成,它接收一個元組並運行一系列的柵格計算以生成五個柵格(總體,沿岸,表面,地下,深度),然後爲每個柵格調用函數processtable
以將值寫入使用arcpy.sa.ZonalStatisticsAsTable
DBF,添加使用arcpy.AddField_management
一些領域,DBF轉換爲使用arcpy.TableToTable_conversion
一個csv,最後刪除使用arcpy.Delete_management
DBF文件。ArcPy中+多:錯誤:無法保存柵格數據集
基於一些other SO posts,我已經將我的代碼包裝在main()
中,因此multiprocessing.Pool
會被認爲很好玩。我用main()
創建元組和pool.map
做多。我使用tempfile
包爲dbf文件選擇名稱以避免名稱衝突; csv文件名保證不與其他線程衝突。
我已經測試我的代碼與for循環,它工作正常,但是當我嘗試使用pool.map
我得到
RuntimeError: ERROR 010240: Could not save raster dataset to C:\Users\Michael\AppData\Local\ESRI\Desktop10.4\SpatialAnalyst\lesst_ras with output format GRID.
這到底是怎麼回事?此錯誤不會在非多進程版本的代碼顯示出來,我不隨地---然後重新寫出來的柵格,我不知道該怎麼arcpy
涉及中間柵格(我肯定不要」不要以爲它會讓他們記憶猶新---它們太大了)。我是否需要告訴arcpy
有關處理多處理工作的光柵計算的方式?我已經在下面包含了我的python文件。
import arcpy
arcpy.CheckOutExtension("Spatial")
import arcpy.sa
import numpy
import multiprocessing
import tempfile
bathymetry_path = r'C:/GIS workspace/RRE/habitat.gdb/bathymetry_NGVD_meters'
zones_path = r'C:/GIS workspace/RRE/habitat.gdb/markerzones_meters'
table_folder = r'C:/GIS workspace/RRE/zonetables'
bathymetry = arcpy.sa.Raster(bathymetry_path)
zones = arcpy.sa.Raster(zones_path)
def processtable(raster_obj, zone_file, w, z, out_folder, out_file):
temp_name = "/" + next(tempfile._get_candidate_names()) + ".dbf"
arcpy.sa.ZonalStatisticsAsTable(zone_file, 'VALUE', raster_obj, out_folder + temp_name, "DATA", "SUM")
arcpy.AddField_management(out_folder + temp_name, "wse", 'TEXT')
arcpy.AddField_management(out_folder + temp_name, "z", 'TEXT')
arcpy.CalculateField_management(out_folder + temp_name, "wse", "'" + str(w) + "'", "PYTHON")
arcpy.CalculateField_management(out_folder + temp_name, "z", "'" + str(z) + "'", "PYTHON")
arcpy.TableToTable_conversion(out_folder + temp_name, out_folder, out_file)
arcpy.Delete_management(out_folder + temp_name)
def computeplane(wsedepth):
wse = wsedepth[0]
depth = wsedepth[1]
total = bathymetry < depth
littoral = total & ((wse - bathymetry) < 2)
surface = total & ~(littoral) & ((total + wse - depth) < (total + 2))
profundal = total & ((total + wse - depth) > (total + 5))
subsurface = total & ~(profundal | surface | littoral)
# zonal statistics table names
total_name = 'total_w' + str(wse) + '_z' + str(depth) + '.csv'
littoral_name = 'littoral_w' + str(wse) + '_z' + str(depth) + '.csv'
surface_name = 'surface_w' + str(wse) + '_z' + str(depth) + '.csv'
subsurface_name = 'subsurface_w' + str(wse) + '_z' + str(depth) + '.csv'
profundal_name = 'profundal_w' + str(wse) + '_z' + str(depth) + '.csv'
# compute zonal statistics
processtable(total, zones, wse, depth, table_folder, total_name)
processtable(littoral, zones, wse, depth, table_folder, littoral_name)
processtable(surface, zones, wse, depth, table_folder, surface_name)
processtable(profundal, zones, wse, depth, table_folder, profundal_name)
processtable(subsurface, zones, wse, depth, table_folder, subsurface_name)
def main():
watersurface = numpy.arange(-15.8, 2.7, 0.1)
# take small subset of the tuples: watersurface[33:34]
wsedepths = [(watersurface[x], watersurface[y]) for x in range(watersurface.size)[33:34] for y in range(watersurface[0:x+1].size)]
pool = multiprocessing.Pool()
pool.map(computeplane, wsedepths)
pool.close()
pool.join()
if __name__ == '__main__':
main()
UPDATE
一些更多的偵探發現,這與其說是一個multiprocessing
問題,與ArcGIS中確實光柵處理方式的問題。柵格代數結果寫入默認工作區中的文件;在我的情況下,我沒有指定一個文件夾,所以arcpy
正在寫入一些AppData文件夾的柵格。基於您的代數表達式,ArcGIS使用基本名稱,如Lessth,Lessth_1等。由於我沒有指定工作區,所有multiprocessing
線程正在寫入此文件夾。雖然單個arcpy
過程可以跟蹤的名字,多進程都儘量寫同樣的光柵名並撞到其他進程的鎖。
我試圖創建在computeplane
開始隨機工作區(文件GDB),然後在年底將其刪除,但arcpy
通常不及時和DELETE語句的過程中死機釋放鎖。所以我不知道如何繼續。