去年花了3天時間,學習了Python 的語法,除當時寫了幾個小游戲之外,一直沒有用于實踐解決實際問題。解決實際問題是學習編程的最好方法。學習Python最初的目的是用python寫arcgis腳本,完成批處理。剛好,一個師妹最近要處理大批量的global30的數據,于是我試著用Python寫了個批處理。做一個記錄,記下寫代碼過程中遇到到問題和解決辦法,方便以后查閱。
程序目標
將800多個分副的Global30數據中的人工建設用地提取出來,轉成Shaplefile文件,再合成一個完整的shapefile文件。
用到的arcgis 模塊有 Feature Clip, Reclassify, PolygontoRaster, Feature Merge.
程序實現
要素遍歷
批處理程序第一步肯定是要獲取需要處理的所有文件,也就是文件遍歷。Arcpy站點包中,為Arcgis的Feature\Raster\Table等要素專門設置了函數,分別為arcpy.ListFeatureClasses()
、arcpy.ListRasters()
、arcpy.ListTable()
等。返回的是文件名的list集合。
功能實現
ArcGis 中對每一個ArcToolBox 中的工具基本都有對應的Python語句,可以從幫助中查詢。
FeatureClip
arcpy.Clip_management(precRaster, "#", outfile, shapeList[i], "0", "ClippingGeometry")
Reclassfiy
Reclassify(outfile, "Value", RemapRange([[0, 79, "NODATA"], [80, 80, 1], [81, 255, "NODATA"]]), "NODATA")
Reclassify 中提供兩種重分類的賦值方法,意思范圍RemapRange
,另外是一對一賦值RemapValue
.
Reclassify 如果沒有柵格屬性表,可能回報錯。因此在Reclassify 前要創建一個柵格屬性表。可用arcpy.BuildRasterAttributeTable_management(outfile, "Overwrite")
創建。
PolygontoRaster
arcpy.RasterToPolygon_conversion(outReclass, outPolygons, "NO_SIMPLIFY", "Value")
Feature Merge
arcpy.Merge_management(featureList, "OutFiles.shp")
輔助函數
文件名解析
文件名解析也是批處理中重要的一個內容,可以方便地控制輸出文件。可用OS 模塊或者,用split分割輸入文件名。再用 + 連接新的字符串,形成輸出文件名。
調試
調試是寫程序的重要工作,“行百里者半九十”,調試就是那最后的占一半的10percent。
Python 中調試的語句是:
try:
語句
except:
錯誤處理
可以提示錯誤在哪兒,也可以進行下一步操作。
完整代碼
# -*- coding: utf-8 -*-
##Clip
import arcpy
from arcpy import env
from arcpy.sa import *
# arcpy.env.workspace = r"D:\JM\HelpOthers\global20\data"
arcpy.env.workspace = r"E:\goble"
rasterList = arcpy.ListRasters("*")
shapeList = arcpy.ListFeatureClasses("*")
# print rasterList, shapeList
n = len(rasterList)
m = len(shapeList)
print "共有" + str(n) + "副柵格"
error = open("E:\\goble\\error.txt", "w")
eundo = open("E:\\goble\\eundo.txt", "w")
enoarti = open("E:\\goble\\enoarti.txt", "w")
# outfile = "test_clip.tif"
if m == n:
for i in range(0, n, 1):
# 柵格裁剪 如果裁剪失敗,提示錯誤但不終止重新
precRaster = rasterList[i]
# print precRaster, shapeList[i]
outfile = arcpy.env.workspace + "\\temp\\" + precRaster.split(".")[0] + "_clip.tif"
try:
print "clip Raster"
arcpy.Clip_management(precRaster, "#", outfile, shapeList[i], "0", "ClippingGeometry")
except:
print precRaster, shapeList[i],"Clip Failed"
print arcpy.GetMessages()
error.write(precRaster+ " " +shapeList[i]+" Clip Failed")
error.write(arcpy.GetMessages())
outfile = precRaster
pass
# 重分類
arcpy.CheckOutExtension("Spatial")
try:
print "Reclassify"
outReclass = Reclassify(outfile, "Value", RemapRange([[0, 79, "NODATA"], [80, 80, 1], [81, 255, "NODATA"]]), "NODATA")
outfile = arcpy.env.workspace + "\\temp\\" + precRaster.split(".")[0] + "_Reclass.tif"
outReclass.save(outfile)
except:
print precRaster, shapeList[i],"Reclassify Failed"
print arcpy.GetMessages()
error.write(precRaster+" "+ shapeList[i]+" Reclassify Failed")
error.write(arcpy.GetMessages())
str1 = precRaster+" "+ shapeList[i] + " undo"
eundo.write(str1)
continue
print "判斷個數"
# 獲取分類后的柵格獨立值個數,判斷是否有80這個值,有的話輸出shape,沒有則不輸出
arcpy.BuildRasterAttributeTable_management(outfile, "Overwrite")
# 獲取唯一值函數
uniq = arcpy.GetRasterProperties_management(outfile, "UNIQUEVALUECOUNT")
# 柵格轉矢量
print "轉柵格"
if str(uniq) != str(0):
outPolygons = arcpy.env.workspace + "\\ShapeFile\\" + precRaster.split(".")[0] + ".shp"
arcpy.RasterToPolygon_conversion(outReclass, outPolygons, "NO_SIMPLIFY", "Value")
# else:
# print precRaster + "NO 80"
#合并所有shapefiles
else:
print precRaster + "no 80"
str2 = precRaster + " "
enoarti.write(str2)
arcpy.env.workspace = arcpy.env.workspace + "\\ShapeFile"
featureList = arcpy.ListFeatureClasses("*")
arcpy.Merge_management(featureList, "Global30all.shp")
print "完成啦!"
eundo.close()
error.close()
enoarti.close()
else:
print "個數不一致"