这是一个非常普遍的问题。我只是想知道GIS程序员使用哪些提示和技巧来加快导入到工具箱中并运行的arcpy脚本的速度。

我每天都在工作,编写一些小的脚本来帮助我办公室的非GIS用户处理GIS数据。我发现,ArcGIS 10.0的处理通常比9.3.1慢,有时在运行python脚本时会变得更慢。

我将列出一个接管脚本的特定示例。 24小时运行。这是一个循环,针对缓冲区中的每个形状将缓冲区中的栅格区域制成表格。缓冲区大约有7000个形状。我不认为它应该运行这么长时间。

while x <= layerRecords:

    arcpy.SetProgressorLabel("Tabulating Row: " + str(x) + " of " + str(ELClayerRecords))
    arcpy.SelectLayerByAttribute_management(Buff,"NEW_SELECTION", "Recno = " + str(x))                                  # Selecting the record
    TabulateArea(Buff, "Recno", MatGRID, "VALUE", ScratchWS + "/tab" + str(z) +".dbf", nMatGRIDc)                          # Tabulate the area of the single row

    arcpy.AddMessage ("          - Row: " + str(x) + " completed")
    x = x + 1
    z = z + 1


在有人说之前,我已经在整个缓冲区上运行了制表区域,但是如果在1条以上的记录上运行,则会产生错误。这是一个有缺陷的工具,但是我必须使用它。

无论如何,如果有人对如何优化或加速此脚本有任何想法,将不胜感激。否则,在ArcGIS中使用python时,您有任何提高Python速度的技巧吗?

#1 楼

以下是一些有助于加快处理速度的潜在建议:


按属性选择图层可以在仅使用Python的脚本中进行,而无需启动ArcGIS Desktop。您需要将“ buff”参考从基于文件的参考转换为“ ArcGIS layer”参考,ArcGIS可以根据该参考处理选择查询。在“ while”循环上方使用arcpy.MakeFeatureLayer_management(“ buff”,“ buff_lyr”),然后在while循环下方更改引用以使用“ buff_lyr”。
使用in_memory工作区处理尽可能多的GP操作尽可能...使用arcpy.CopyFeatures_management(shapefile,“ in_memory \ memFeatureClass”)将源移到内存中。仅当您有足够的RAM来将所需的所有要素类读取到内存中时,此方法才有效。但是请注意,有些GP操作无法使用in_memory工作空间(例如Project工具)运行。

摘自ArcGIS 9.3联机帮助文章“中间数据和临时工作空间”(请注意,该语言已从10.0和10.1帮助中删除):


注意:只能将表和要素类(点,线,面)
写入in_memory工作空间。 in_memory工作空间不支持扩展的地理数据库元素,例如子类型,域,表示形式,拓扑,几何网络和网络数据集。
只能编写简单的要素和表。


从ArcGIS 10.1联机帮助文章“使用内存工作区”中:


在决定将输出
写入到计算机时,必须考虑以下因素:内存中的工作区:


写入内存中的工作区的数据是临时的,在应用程序关闭时将被删除。
表,要素类和栅格可以被写入内存中的工作区。
内存工作空间不支持扩展的地理数据库元素,例如子类型,域,制图表达,拓扑,几何网络和网络数据集。不能在内存工作空间中创建要素数据集或文件夹。



评论


这太妙了!我一直在寻找一种在ArcMap之外使用选择的方法,但是到目前为止还没有成功。在这个问题上,它实际上使我的每行时间从20秒降低到了13秒左右。但是,我做了一个快速的其他工作,并在循环中进行了MakeFeatureLayer的操作,它减少到了9秒。我是通过从每个形状制作一个特征而不是从特征层中制表来实现的。如果可能的话,我仍然想进一步降低它,但是已经是一个更快的过程了!

–科迪·布朗
2012年8月20日15:16



如#2所述,使用CopyFeatures复制源数据in_memory,然后根据in_memory源创建feature_layer。虽然初始复制到内存可能会提前几秒钟,但是您可能会发现,复制功能+ tabulate_areas的处理总处理时间比当前模型要快。

– RyanKDalton
2012年8月20日下午16:55

我也尝试过,看来该解决方案可以使循环过程更快,但事实并非如此。在循环中创建要素图层大约每个循环需要8-10秒,而在循环之前创建要素图层则每个循环大约需要11-14秒。我不太清楚为什么会这样,因为您的解决方案听起来像处理速度会更快。我有8GB的RAM,所以我怀疑那是问题所在。

–科迪·布朗
2012年8月20日17:22



同样,在循环之前将要素处理到in_memory中,然后仍然在循环中创建要素层会导致性能稍快。每个循环几乎每行停留8秒。这将使总处理时间从26小时减少到22小时。

–科迪·布朗
2012年8月20日17:32



添加您的想法后,我的脚本得到了极大的改进。多谢您的光临,以及大家的帮助!

–科迪·布朗
2012年8月21日17:27



#2 楼

一般的python优化技术可以为您节省大量时间。

使用内置的cProfile模块可以降低脚本中的保留位置,这是一种非常不错的技术:
from cProfile import run
run("code") # replace code with your code or function


使用较小的数据样本进行测试将使您能够确定哪些函数调用花费的时间最多。

用于更快的python代码的常规指针:


列表解析通常比循环更快
生成器一次生成一个项目,而不是一次生成整个列表。
在Python 2中使用xrange而不是range(不是3)中必不可少的。
在确定某项是否存在于集合中时,集合可以预先显示列表,但在迭代其内容时通常比列表慢。

函数调用可能会降低性能来源

更多提示和详细信息,请点击此处查看Python性能提示和此处的10条Python优化提示和问题。

关于您的脚本,我无法在ArcPy方面发表评论,因为我没有在此计算机上安装Arc,但是您可能希望尝试使用for循环而不是while循环来查看是否可以改善任何事情。同样x = x + 1可以写成x + = 1:

for record in layerRecords:
arcpy.SetProgressorLabel("Tabulating Row: " + str(x) + " of " + str(ELClayerRecords))
arcpy.SelectLayerByAttribute_management(Buff,"NEW_SELECTION", "Recno = " + str(x))                                  # Selecting the record
TabulateArea(Buff, "Recno", MatGRID, "VALUE", ScratchWS + "/tab" + str(z) +".dbf", nMatGRIDc)                          # Tabulate the area of the single row

arcpy.AddMessage ("          - Row: " + str(x) + " completed")
x+=1
y+=1


评论


我使用了最后一个项目符号上留下的两个链接,并通过一些快速修复可以真正帮助我的脚本!

–科迪·布朗
2012年8月20日15:21

如果我能给出两个正确答案,我会。虽然您的答案确实提供了许多有关如何加快python速度的想法,但@RyanDalton提供了影响最大的想法。万分感谢!

–科迪·布朗
2012年8月21日在17:25

#3 楼

确保您正在写入计算机上的内部驱动器。在不需要时通过网络进行访问确实会减慢处理速度。作为过程的第一步,复制数据甚至更快,以确保后续的读写操作尽可能快。

在ArcMap之外完全运行脚本可以更快。如果在处理过程中不需要地图,则不要使用ArcMap。

评论


我发现从ArcCatalog在模型内部运行脚本(本身在“计算值”对话框中)比在ArcMap中从ArcPy窗口运行相同脚本的处理速度更快。不过,这纯粹是轶事。

–辛迪·贾亚库玛(Cindy Jayakumar)
2012年8月20日下午5:09

我相信我确实需要一张表格来使制表法正常工作,但是我将尝试这种方法。如果它在ArcMap之外运行,我敢打赌它会加快速度。另外,我已经在本地磁盘上运行了,这已经使脚本的速度提高了一倍。

–科迪·布朗
2012年8月20日在12:55

遗憾的是,Select在ArcMap之外无法使用,这是必需的,因为我需要逐个绘制表格。

–科迪·布朗
2012年8月20日13:49

@ CodyBrown-您对选择不能在ArcMap会话外部工作不正确。查看有关使用MakeFeatureLayer工具的答复。

– RyanKDalton
2012年8月20日15:09

瑞安是对的。单独使用选择工具时,它会创建空间数据或表数据的表视图。在ModelBuilde或脚本中使用它时,必须创建一个视图,并根据情况使用MakeFeatureLayer工具创建它。

– dchaboya
2012年8月20日19:24



#4 楼

这可能无法回答您在ArcMap中运行ArcPy工具的问题,但是当我需要使用地理处理工具和Python进行一些繁琐的处理时,我倾向于使用IDE PyScripter在GIS系统之外运行它。我发现它运行得更快。我还为小型临时输出数据集使用了RAMDISK(有点像in_memory工作区)。

它们是我的首要提示! :)

评论


为了使这个答案有些混乱,当从Python IDE运行脚本时,许多注入了回溯功能以帮助监视变量和其他各种调试帮助。如果此功能被称为ALL THE TIME的话,它可能会大大降低脚本的运行速度,有时此功能会隐式安装而无需用户干预。我观察到一个特殊的病理情况,其中在ArcMap中运行Python脚本的时间为4分钟,而来自Wing IDE的相同脚本则花费了3个小时。从不带Wing的Python.exe运行该程序后,它回到了大约2-3分钟的运行时范围。

–Jason Scheirer
2012年8月19日在20:33

我一直很头疼,无法在ArMap上调整脚本,有时我无法完全解决,直到我转向Pyscripter为止,与Arcmap相比,它可以节省执行时间,而无需使用任何优化技巧。

– geoogeek
2012年10月12日在11:23

@JasonScheirer您是否发现Wing中的调整功能可以将其关闭?我确定有一个。

–科蒂斯价格
2013年6月5日17:40

#5 楼

尝试注释掉arcpy.SetProgressorLabel并查看您加快了多少。
我发现,回到DOS呆滞的任何屏幕输出都会大大减慢处理时间。如果您确实需要查看该输出,请尝试在第N个循环中显示它。

#6 楼

确保删除所有未使用的import xxxx行。

(即,如果您还没有使用任何数学函数,但您拥有import Math,则从脚本加载开始将花费一些时间)对运行的单个脚本(例如您的脚本)产生影响,它将影响经常重复运行的所有脚本。

评论


我怀疑任何标准的Python模块花费的时间都不超过arcpy模块初始化的时间的千分之一。

–blah238
2012年8月18日在4:24

@ blah238 import数学可能是一个不好的例子。但是,某些较大的ArcPy库确实需要花费大量时间来加载。

– nagytech
2012年8月18日在4:54

这仍然只能节省几秒钟(最多!),而不是几小时

– Mike T
2012年8月18日下午5:38

@MikeToews对于频繁且重复运行的脚本,在几天/几周等过程中,要花费几秒钟的时间。尽管这不能解决OP的主要问题,但他确实要求提供一般性提示。

– nagytech
2012年8月18日在8:18