搜罗全网!ArcGIS二次开发Python(arcpy)指南(四): 工作空间 设置好,解决超过一半的烦恼
前言:带你搞定当前工作空间和临时工作空间的区别,工作空间不仅仅能方便数据文件的存取,更是许多 ArcPy 方法运行的隐藏前提条件;搞定工作空间,解决超过一半的错误...
文章的写作顺序:当前工作空间->临时工作空间->当前工作空间与临时工作空间的区别->内存空间。工作空间是什么
工作空间( workspace)不是 ArcPy&ArcGIS 中独有的概念,在很多软件和编程语言中都有这样一个概念;但总的来说,意思都是差不多的,指当前使用项目的存放位置或者运行命令行和脚本文件的位置。注意区分两种工作空间,一个是 Python 编程环境的,通常来说,Python 运行文件所在的文件夹就是工作空间;另一个是 ArcPy 自带的工作空间,注意区分。我有的时候很喜欢把当前 Python 的工作空间设置为 ArcPy 的当前工作空间,特别是笔者写的这些教程示例:import arcpyimport osarcpy.env.workspace = os.getcwd()在 ArcPy 中,工作空间不仅可以是一个文件夹也可以是一个数据库。同时在 ArcPy 中有当前工作空间(currentWorkspac)和临时工作空间(scratchWorkspace)这两种,再加上我自己命名的内存空间(inmemory),共三种。当前工作空间
计算机中的抽象概念都是为了更好的方便用户使用。配置当前工作空间的关键字是 workspace(env)。而工作空间这个概念的英文名就是 workspace,所以有的读者会被混淆,一个是具体操作一个是范围较大的概念。在 ArcPy 中使用 workspace(env)用于配置当前工作空间,如下面示例代码:arcpy.env.workspace = "path"当前工作空间可以是一个文件夹也可以是数据库,取决于不同的需求;不管是文件夹还是地理数据库都为存储和管理 ArcGIS 地理信息提供了主要容器。使用 gdb 数据库作为当前工作空间的示例见于 Chapter/code1.py 文件:# -*- coding:utf-8 -*-import arcpyimport osarcpy.env.overwriteOutput = Truelyr_p = "../SHP/Boroughs.shp"gdb = "YC.gdb"if not arcpy.Exists(gdb): # ▶注释1◀ arcpy.CreateFileGDB_management(os.getcwd(), gdb)arcpy.env.workspace = "YC.gdb"arcpy.CopyFeatures_management(lyr_p, "Water2")arcpy.Delete_management("Water2")▶注释1◀:确保 YC.gdb 数据库的存在,如果不存在的话新创建一个 gdb 数据库,这是一个常见操作。1.为什么使用当前工作空间1.1 便于使用在 ArcPy 中读取、输出文件都需要指定文件存放的位置(其文件路径),通常来说文件的位置信息都是很长的,动不动就是几十个字符,例如:G:/MoveOn/arcpyTutoraial/SHP/Boroughs.shp输入如此长的数据名称非常繁琐、麻烦并且容易出错,所以为了简化名称、方便管理数据,我们需要设置当前工作空间。而在设置了当前工作空间后,我们可以直接使用文件的基本名称,而不是原来的完整名称(地址):如 Boroughs.shp 或者 Boroughs。1.2 避免报错我直接使用文件的完整路径名还会报错?我非常肯定的告诉你:“部分会报错,部分不会”,这是一个会坑死很多初学者的大坑!我以前经常抓耳挠腮,干耗几个小时都没有弄明白的错误,偶尔一次在前面配置好当前工作空间就解决了。找两个典型的示例:第一个是使用 arcpy.da.UpdateCursor:# -*- coding:utf-8 -*-import arcpy# lyr_p = "../SHP/Boroughs.shp"lyr_p = "G:/MoveOn/arcpyTutoraial/SHP/Boroughs.shp"# lyr_p = "../NYC.gdb/Boroughs"with arcpy.da.UpdateCursor(lyr_p, "SHAPE@") as cursor: for row in cursor: print row[0]
运行后直接报错,错误信息如上。注意我是直接使用的完整文件路径信息哦,也会报错。在设置好当前工作空间之后,运行同样的代码,运行成功,完整示例代码如下,可见文件 Chapter4/code2.py 上半部分:# -*- coding:utf-8 -*-import arcpyimport osarcpy.env.workspace = os.getcwd()# lyr_p = "../SHP/Boroughs.shp"lyr_p = "G:/MoveOn/arcpyTutoraial/SHP/Boroughs.shp"# lyr_p = "../NYC.gdb/Boroughs"with arcpy.da.UpdateCursor(lyr_p, "SHAPE@") as cursor: for row in cursor: print row[0]
第二个是使用 arcpy.CopyFeatures_management 方法:# -*- coding:utf-8 -*-import arcpyarcpy.env.overwriteOutput = Truelyr_p = "../SHP/Boroughs.shp"arcpy.CopyFeatures_management(lyr_p, "out.shp")
直接报错,按理来说程序会输出一个名为 out.shp 文件到文件夹 Chapter4 中。而在配置好当前工作空间后运行成功,示例代码如下,可见于 Chapter4/code2.py 文件的下半部分:import arcpyimport osarcpy.env.workspace = os.getcwd()arcpy.env.overwriteOutput = Truelyr_p = "../SHP/Boroughs.shp"arcpy.CopyFeatures_management(lyr_p, "out.shp")Note:避免 CopyFeatures_management 方法报错的另一个办法就是使用完整输出路径(地址),但是为什么不直接配置好当前工作空间呢,一劳永逸。临时工作空间
在构建需要处理大量中间数据的程序时,可以使用临时工作空间来存放一些我们不需要的数据,当然临时工作空间中的数据不会自动删除,在不需要这些数据的时候用户可以自行删除。设置临时工作空间的方式如下:arcpy.env.scratchWorkspace = "path"1.使用临时文件夹和临时数据库临时工作空间的设置方式和当前工作空间相似,但是用法却有些许的不同:我们一般不会直接使用临时工作空间,而是使用创建在临时工作空间下的临时文件夹和临时数据库。另外临时文件夹设置数据库是没有什么意义的,它会转而表示数据库所在的文件夹。1.1 使用内置方法创建临时工作空间下面可以派生出两个新方法:arcpy.env.scratchFolder 和 arcpy.env.scratchGDB,这两个方法可以自动在我们设置的临时工作空间中创建一个临时文件夹和临时数据库:import arcpyimport osarcpy.env.overwriteOutput = Truearcpy.env.scratchWorkspace = os.getcwd()print arcpy.env.scratchFolderprint arcpy.env.scratchGDB对你没有看错,在设置临时工作空间后,直接 print 输出就可以直接在临时工作空间中创建临时文件夹和临时数据库(官方示例就是使用的 print)。运行后会在该文件夹中创建以下文件夹和数据库:
1.2使用字符串创建实际上有更好的用法,我们可以使用 %scratchFolder% 和 %scratchGDB% 字符串来创建,示例代码可见于 Chapter/code3.py :# -*- coding:utf-8 -*-from __future__ import unicode_literalsimport arcpyimport osarcpy.env.overwriteOutput = Truearcpy.env.scratchWorkspace = os.getcwd()lyr_p = "../SHP/Boroughs.shp"arcpy.CopyFeatures_management(lyr_p, "%scratchGDB%/out1")arcpy.CopyFeatures_management(lyr_p, "%scratchFolder%/out2.shp")print(arcpy.env.scratchFolder)print(arcpy.env.scratchGDB)在显式的将运行 py 文件的位置作为临时工作空间后,在输出数据名称中加入 %scratchGDB% ,系统会自动在该临时工作空间搜寻是否有名为 scratch.gdb 的数据库,如果没有就会自动创建,然后将数据存储在该数据库中;同理使用 %scratchFolder% 会自动在该临时工作空间中搜寻 scratch 文件夹,如果没有会自动创建同名文件夹。1.3 未设置临时工作空间时如果在没有设置临时工作空间的前提下使用 arcpy.env.scratchFolder 和 arcpy.env.scratchGDB 或者 %scratchFolder% 和 %scratchGDB%,同时用户有足够的系统权限的话,临时文件夹和临时数据库会被创建在 C:\Users<user>\AppData\Local\Temp 中,或者 Windows XP 的 C:\Documents and Settings<user>\Localsystem\Temp 中。2.使用唯一名称我们不关心临时工作空间中的数据名称,没有太大的意义,但是也需要获取其名称,要么是作为下一步处理的参数传入,要么就是避免同名文件覆盖可能还会再利用的数据。所以处理数据名称也是一件烦人的事,特别是取名字。ArcPy 中提供了CreateScratchName 方法可以帮助我们自动创建唯一名称,可以帮助用户专注于功能的实现而不必担心文件名称的问题。示例可见于 Chapter/code4.py 文件:# -*- coding:utf-8 -*-from __future__ import unicode_literalsimport arcpyimport osarcpy.env.overwriteOutput = Truearcpy.env.scratchWorkspace = os.getcwd()lyr_p = "../SHP/Boroughs.shp"name1 = arcpy.CreateScratchName(workspace=arcpy.env.scratchFolder)name2 = arcpy.CreateScratchName(workspace=arcpy.env.scratchGDB)print "name1: {}".format(name1)print "name2: {}".format(name2)arcpy.CopyFeatures_management(lyr_p, name1)arcpy.CopyFeatures_management(lyr_p, name2)将 Boroughs.shp 文件分别保存到临时文件夹和临时数据库中。CreateScratchName 方法需要一个 workspace 参数,传入临时文件夹和临时数据库都是可以的,该方法返回一个完整的文件名称(地址),输出如下:name1: G:\MoveOn\arcpyTutoraial\Chapter4\scratch\xx0name2: G:\MoveOn\arcpyTutoraial\Chapter4\scratch.gdb\xx0可以看到文件的基本名称是“xx”加上数字组成的,如果再往里面添加数据,基本名称就是“xx1”,以此类推。这样可以有效的避免覆盖同名文件,同时不用劳心去取名字(对于笔者来说,取名字真的是一个难点!),然后只需使用变量名就可以实现文件的复用。当前工作空间和临时工作空间混合使用
使用了当前工作空间不一定会再使用临时工作空间,而使用了临时工作空间的一般会使用当前工作空间。当程序源代码中同时设置了这两种工作空间的话,有什么注意事项呢?以下示例可见于文件 Chapter/code5.py:# -*- coding:utf-8 -*-import arcpyimport osarcpy.env.overwriteOutput = True# ▶注释1◀arcpy.env.scratchWorkspace = os.getcwd()arcpy.env.workspace = "../"lyr_p = "../SHP/Boroughs.shp"# ▶注释2◀arcpy.CopyFeatures_management(lyr_p, "out5")# ▶注释3◀arcpy.CopyFeatures_management( lyr_p, os.path.join(arcpy.env.scratchFolder, "out5"))arcpy.CopyFeatures_management(lyr_p, "%scratchFolder%/out5_1")▶注释1◀:笔者在这里同时设置了当前工作空间和临时工作空间;将外部的 arcpyTutoraial 文件夹设置为当前工作空间,而内部的 arcpyTutoraial/Chapter4 文件夹设置为临时工作空间,那么问题来了:▶注释2◀ 输出文件 out5 会被另存到哪里呢?会被保存到当前工作空间,即 arcpyTutoraial 文件夹中。只要使用的是基本名称(out5),该名称便会与当前工作空间相连,而不与临时工作空间相连。▶注释3◀:那如何保存到临时工作空间呢?使用这两种方法即可,一个是使用 arcpy.env.scratchFolder,另一个是使用 %scratchFolder% 字符串作为基本名称。内存空间
内存空间(in_memory)也叫内存工作空间,ArcGIS 提供了一个可写入输出要素类和表的内存工作空间。将文件数据保存到计算机的内存中,而不是磁盘里,这样可以节约计算机保存数据到磁盘、再从磁盘读取到内存的开销。理论上可以提高程序的运行速度、减少运行时间,同时在程序运行结束后,不用再去删除中间数据,因为程序运行结束后,内存中的相关数据都会自动删除。听到这里,是不是跃跃欲试?但是内存容量有限,通常大家的电脑内存都是8G或者16G,然后程序系统又会占用一部分,空余的不多,如果想要处理大规模的数据是比较吃力的,很有可能最后就因为内存空间不够了而出错退出。开一扇窗也会关一扇窗,上帝是公平的,除非你有钱,整个1G内存的计算机,连上帝都被收买了。如何将数据保存到计算机运行内存(in_memory)中呢?以下示例可见于文件 Chapter/code6.py:# -*- coding:utf-8 -*-import arcpyimport osarcpy.env.overwriteOutput = Truearcpy.env.workspace = os.getcwd()lyr_p = "../SHP/Boroughs.shp"# ▶注释1◀inmemory = "in_memory/line1"arcpy.FeatureToLine_management(lyr_p, inmemory)arcpy.CopyFeatures_management(inmemory, "out6")# ▶注释2◀del inmemory将 Boroughs.shp 要素类转换为线要素类,保存在内存中,然后再另存到磁盘中。▶注释1◀:要写入 in_memory 工作空间,需要指定以 in_memory 开头的输出数据集路径,例如这里的 in_memory/line1。▶注释2◀:由于内存空间不大,不需要的中间数据可以在程序还没有结束前就手动删除,为其它数据空出空间。官方推荐使用 arcpy.Delete_management 方法来删除内存空间中的数据,当然这个方法也可以直接清空整个内存空间。注意事项:写入内存工作空间的数据是临时性的,将在关闭应用程序时被删除。表、要素类和栅格可写入内存工作空间。内存工作空间不支持扩展的地理数据库元素,如子类型、属性域、制图表达、拓扑、几何网络以及网络数据集。不能在内存工作空间中创建要素数据集或文件夹。补充和总结
在工具箱的数据管理工具中有一个工作空间工具集,提供了一些关于工作空间的方法,较为简单,大家可以了解一下:
看完本章节,你可以掌握正确设置当前工作空间;你能明白部分错误的来源可能是工作空间的问题;掌握使用临时工作空间及其派生的临时文件夹和临时数据库;了解当前工作空间和临时工作空间的区别:不仅仅是概念不同,其内部用法也不同;掌握使用内存空间(in_memory)。结束语
该章节内容到这里就结束啦,可以收藏下来哦,如果以后有遇到相关问题,可以再来细细的查阅。使用版本:Windows 10PyCharm 2020.3.3ArcGIS 10.3Python 2.7.8源代码、教学文档离线小册子下载: