arcgis编写的python程序怎么用,arcgis api for python

大家好,小编来为大家解答以下问题,基于arcgis的python编程秘笈(第2版),基于arcgis的python编程秘笈 下载,现在让我们一起来看看吧!

arcgis编写的python程序怎么用,arcgis api for python_第1张图片

前面《基于ArcGIS的python编程 10、根据Excel表格批量生成点数据,批量裁剪》的程序顺利跑完大概要1小时20分,确实很慢,想起之前看到有利用python的多线程多进程去提高效率的案例,这里尝试利用多线程多进程对程序进行优化,提高程序的运行效率。自己对于多线程多进程的理解与应用都是一知半解,这里就不再班门弄斧,分享一篇文章《进程与线程的一个简单解释》,我觉得这蛮好解释了多进程多线程的含义python创意。有兴趣的可以去好好理解一下。

批量生成点数据工具的优化(多进程的运用):

思路还是与上一篇一样,只不过把上一次的代码进行功能拆分,拆分为一个个功能函数,然后通过多进程多线程去充分利用电脑的CPU,多核同时运行同一个功能函数,这样就可以提高程序的效率。因为对多线程多进程不太熟悉,只能参考别人的案例,去模仿;虽然也应用了多线程多进程,但是程序还有很大的改善空间,刚刚接触这个新的知识,只能接下来继续去完善。

完整代码如下:

#coding=utf-8

import arcpy

import xlrd

import time

import multiprocessing

#获得表格的名字

def gettablename(in_table):

tablenamelist=[]

tablepaths=in_table.split(';')

for path in tablepaths:

name=path.split('\\')[-1].split('.')[0]

tablenamelist.append(name)

return tablenamelist

#根据表名,保存路径,坐标参考新建点要素

def CreateFeaturclass(tablename,savepath,spatial):

if arcpy.Exists(savepath + '\\' + tablename + '.shp')==False:

arcpy.CreateFeatureclass_management(savepath,tablename,'POINT','','','',spatial)

else:

pass

#根据表的路径,保存的路径,为刚刚创建的点要素添加字段

def AddField(tablepath,savepath):

featurename=tablepath.split('\\')[-1].split('.')[0]

data=xlrd.open_workbook(tablepath)

sh=data.sheets()[0]

ziduanNamelist=sh.row_values(0)

for ziduan in ziduanNamelist:

arcpy.AddField_management(savepath+'\\'+featurename+'.shp',ziduan,'TEXT')

#根据表名,点要素的路径,表里的内容写入点要素中

def InsertRow(savepath,tablepath):

featurename = tablepath.split('\\')[-1].split('.')[0]

data = xlrd.open_workbook(tablepath)

sh = data.sheets()[0]

ziduanNamelist = sh.row_values(0)

rownum = sh.nrows

Insercur = arcpy.InsertCursor(savepath + '\\' + featurename + '.shp')

for rowid in range(1,rownum):

newpnt = arcpy.Point()

newpnt.X = float(str(sh.cell(rowid, 2).value))

newpnt.Y = float(str(sh.cell(rowid, 1).value))

pointGeo = arcpy.PointGeometry(newpnt)

newrow = Insercur.newRow()

newrow.shape = pointGeo

for c in range(0, len(ziduanNamelist)):

newrow.setValue(ziduanNamelist[c],sh.cell(rowid,c).value)

Insercur.insertRow(newrow)

#调用函数

if __name__=="__main__":

in_table = arcpy.GetParameterAsText(0)

savepath = arcpy.GetParameterAsText(1)

spatial = arcpy.GetParameterAsText(2)

tablenamelist=gettablename(in_table)

tablpathlist = in_table.split(';')

pool=multiprocessing.Pool(processes=4)#进程processes的个数根据电脑的核数,我的电脑是4核

#利用多进程创建要素

for tablename in tablenamelist:

pool.apply_async(CreateFeaturclass,(tablename,savepath,spatial,))

pool.close()

pool.join()

time.sleep(1)

#利用多进程添加字段,注意多次运用多进程需要重新创建进程池Pool

pool = multiprocessing.Pool(processes=4)

for tablepath in tablpathlist:

pool.apply_async(AddField,(tablepath,savepath,))

pool.close()

pool.join()

time.sleep(1)

#利用多进程插入数据

pool = multiprocessing.Pool(processes=4)

for tablepath in tablpathlist:

pool.apply_async(InsertRow,(savepath,tablepath,))

pool.close()

pool.join()

前面的文章有些网友问我要源代码,其实源代码我都已经全部帖子文章中了,只需要复制这些代码下来保存为 .py文件,然后再Arcmap中创建脚本工具即可运行,前面的文章已有创建脚本工具的过程,详细过程请参考前面的文章《基于ArcGIS的python编程 6、利用Arcpy制作自定义脚本工具——点线拓扑》;这里不再详细阐述,只是简单的说明一下注意情况;

参数的设置:三个,注意参数的数据类型,是否多值就好。如下图1图1 工具参数设置

工具的界面如图2图2 工具的页面

工具的运行模式:选择第一个,这样的话易于调试,另外如果选择第二个,运行脚本时会不停的打开Arcmap这个程序,有点奇怪;如图3图3 工具的运行模式

运行成功页面如图4;效率有点难以置信,上面一篇文章运行需要1小20分钟左右,相当漫长,这里利用多进程以后,只需要2分钟左右,效率提高了40多倍,节省了很多时间,看来多进程是个好东西,要好好运用。图4 运行成功后的页面

批量裁剪的工具的优化:

这里添加的功能主要是使裁剪要素也可以输入多个,然后利用循环的嵌套,以实现多对对的裁剪功能。因为很多时候我们都遇到过分类或者提取某个要素的需求;比如说我有梅州市的基础数据(国道,省道,县道,高速公路,水系,POI点等),现在我需要梅州行政区域内每个县区的基础数据,那么我们就需要利用梅州市的各个县区的行政区域(面要素,多个)区裁剪梅州市的基础数据(国道,省道,县道,高速公路,水系,POI点等),这样就可以获得每个县区的基础数据了。以前不会程序,也做过类似重复的工作,只能一个面与一个基础数据去裁剪,工作量挺大的。

完整代码如下:

# coding=UTF-8

import arcpy

in_feature= arcpy.GetParameterAsText(0)

in_featurepath = in_feature.split(';')

clip_feature = arcpy.GetParameterAsText(1)

clip_feature_paths = clip_feature.split(';')

out_file = arcpy.GetParameterAsText(2) #保存路径

for clipfeature in clip_feature_paths:

for in_layer in in_featurepath:

name2 = clipfeature.split('\\')[-1].split('.')[0]

name1=in_layer.split('\\')[-1].split('.')[0]

name=name1+"_"+name2

out_layer=out_file+'\\'+name

arcpy.Clip_analysis(in_layer, clipfeature, out_layer)

如果多对对裁剪的数量比较大,也需要一定的时间去运行的,如果想提高效率,也可参考上面程序的案例,巧用多进程即可,这个工具就不再详细阐述了,读者可以自行尝试一下。

总结:

有点奇怪,在python的独立环境中,读取Excel的时候,路径中不能出现中文,否则会报错;但是在Arcgis脚本工具运行时却可以包含中文,不知道什么原因。另外,之前以为python的xlrd模块只能操作.xls版本的表格,但是经过这两次实验,原来xlrd模块可以操作.xls或者.xlsx版本的表格,之前的认知不够。

程序中多次利用进程池Pool调用函数,因为对多进程不太熟悉,所以只创建了一次进程池pool=multiprocessing.Pool(processes=4),导致了第二次利用多进程运行AddField()函数总是报错,后面每使用一次进程池就创建一个,这样就解决了错误。

使用多进程会使电脑的使用内存瞬间爆满,此时电脑很容易卡死或者崩溃;使用time模块的sleep()函数睡眠几秒钟(time.sleep(1),让程序睡眠/暂停1秒钟),可以有效防止电脑由于运行过快,使用内存过高而崩溃。追求高效率的同时,也要注意,要不然电脑很容易吃不消。

另外,自己想在插入属性值的时候(newrow.setValue(ziduanNamelist[c],sh.cell(rowid,c).value))使用多进程,因为如果有好几万个点,如果多进程运行这个函数,同时插入属性值,那么这样效率就大大提高了;这个思路没错,但是忽略了游标里设有表锁,就是防止多进程同时操作一张表,官网的表述如下(斜体字部分为从Esri官网摘录):

游标和锁定

插入和更新游标遵循由 ArcGIS 应用程序设置的表锁。锁能够防止多个进程同时更改同一个表。有两种锁的类型:共享和排它。只要访问表或数据集就会应用共享锁。同一表中可以存在多个共享锁,但存在共享锁时,将不允许存在排它锁。应用共享锁的示例包括:在 ArcMap 中显示要素类时以及在 ArcCatalog 中预览表时。

对表或要素类进行更改时,将应用排它锁。在 ArcGIS 中应用排它锁的示例包括:在 ArcMap 中编辑和保存要素类时;在 ArcCatalog 中更改表的方案时;或者在 Python IDE(例如 PythonWin)中在要素类上使用插入游标时。

如果数据集上存在排它锁,则无法为表或要素类创建更新和插入游标。UpdateCursor 或 InsertCursor 函数会因数据集上存在排它锁而失败。如果这些函数成功地创建了游标,它们将在数据集上应用排它锁,从而使两个脚本无法在同一数据集上创建更新和插入游标。

在 Python 中,在游标释放前保持锁定状态。否则,将会阻止所有其他应用程序或脚本访问数据集,而这是毫无必要的。可通过以下其中一种方法来释放游标:在 with 语句中加入游标,这样可以确保无论游标是否成功完成,都将释放锁

在游标上调用 reset()

完成游标

使用 Python 的 del 语句显示删除游标

ArcMap 中的编辑会话将在其会话期间对数据应用共享锁。保存编辑内容时将应用排它锁。已经存在排它锁时,数据集是不可编辑的。

专栏文章会同步到微信公众号【GIS学习交流】

欢迎大家关注公众号一起交流,一起学习,一起进步!

参考:

你可能感兴趣的:(python,开发语言)