加速以ArcGIS工具运行的Python脚本的方法[关闭]


31

这是一个非常普遍的问题。我只是想知道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的技巧吗?

Answers:


26

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

  1. “按属性选择图层”可以在仅Python脚本中,而无需启动ArcGIS Desktop。您需要将“ buff”参考从基于文件的参考转换为“ ArcGIS layer”参考,ArcGIS可以根据该参考处理选择查询。在“ while”循环上方使用arcpy.MakeFeatureLayer_management(“ buff”,“ buff_lyr”),然后在while循环下方更改引用以使用“ buff_lyr”。

  2. 尽可能使用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联机帮助文章“ 使用内存中的工作空间 ”中:

在决定将输出写入内存工作空间时,必须考虑以下因素:

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

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

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

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

同样,在循环之前将要素处理到in_memory中,然后仍然在循环中创建要素层会导致性能稍快。每个循环几乎每行停留8秒。这将在26小时缩短总的处理时间,以22
科迪布朗

添加您的想法后,我的脚本得到了极大的改进。多谢您的光临和大家的帮助!
科迪·布朗

28

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

降低脚本中保留位置的一种非常好的技术是使用内置的cProfile模块:

from cProfile import run
run("code") # replace code with your code or function

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

更快的python代码的通用指针:

  • 列表理解通常比循环更快
  • 生成器一次只生成一个项目,而不是一次生成整个列表
  • 使用xrange代替python 2中的range(3中不必要)
  • 套可以出预成型件列表,当涉及到确定的项目存在于该集合,但通常比列表慢,当涉及到遍历它们的内容
  • 函数调用可以是昂贵的业绩来源
  • 更多提示和详细信息,请点击此处查看Python性能提示和此处的10条Python优化提示和问题。

关于您的脚本,由于我没有在这台计算机上安装Arc,因此我无法对ArcPy方面进行评论,但是您可能希望尝试使用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

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

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

13

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

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


我发现从ArcCatalog在模型内部运行脚本(本身在Calculate Value对话框中)比从ArcMap的ArcPy窗口运行相同脚本要快。不过,这纯粹是轶事。
Cindy Jayakumar 2012年

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

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

3
@ CodyBrown-您对选择不能在ArcMap会话之外工作不正确。请参阅我关于使用MakeFeatureLayer工具的回复。
RyanDalton 2012年

瑞安是对的。单独使用选择工具时,它将创建空间数据或表数据的表视图。在ModelBuilde或脚本中使用它时,必须创建一个视图,在这种情况下,可以使用MakeFeatureLayer工具创建它。
dchaboya 2012年

6

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

好吧,它们是我的最高提示!:)


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

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

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

5

尝试注释掉arcpy.SetProgressorLabel并查看您加快了多少速度。我发现,任何回到DOS茫然状态的屏幕输出都会大大减慢处理时间。如果您确实需要查看该输出,请尝试每N个循环显示一次。


4

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

(即,如果您尚未使用任何数学函数import Math,则从脚本加载开始将花费一些时间)

尽管这对运行的单个脚本(例如您的脚本)不会产生很大的影响,但它将影响频繁且重复运行的所有脚本。


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

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

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

1
@MikeToews对于频繁且重复运行的脚本,在几天/几周等过程中,要花费几秒钟的时间。尽管这不能解决OP的主要问题,但他确实要求提供一般性提示。
nagytech
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.