ArcPy入门学习指南(含:arcpy in_memory的详细解答)
很多团队在做 ArcGIS 地理处理时,最头疼的是“明明只是临时中间结果,却要频繁落盘到 GDB 或 Shapefile,速度慢、磁盘乱”。作为长期做 Python 与地理处理自动化的从业者,我的经验是:合理利用 ArcPy 的 in_memory 工作空间,可以显著减少磁盘 I/O、提速流水线,还能让脚本更整洁、可维护。

ArcPy 与 in_memory:是什么
ArcPy 是 ArcGIS Pro/ArcMap 提供的 Python 地理处理接口,覆盖数据管理、分析、制图与自动化。in_memory 工作空间可以理解为一个“驻留内存的虚拟地理数据库”,在 Python 进程生命周期内存在(会话结束即释放),支持大多数地理处理工具的中间结果存取(表与要素类为主)。
用一个类比:如果把整条分析流程比作装配线,那么磁盘上的文件就像仓库货架,上架/下架都要搬运;而 in_memory 更像是工作台上的临时托盘,拿取与放回几乎零搬运(I/O),速度自然快。
为什么要用 in_memory
- 性能:减少磁盘读写,常见缓冲、叠置、字段计算等场景可显著缩短耗时。
- 整洁:中间结果不落盘,避免临时数据污染工程目录。
- 可组合:链式调用更顺滑,便于快速搭建与迭代分析流水线。
- 资源亲和:内存可就地复用对象,减少碎片化读写。
核心提示:in_memory 适合“中间态、可丢弃”的临时数据。对需要持久化、复查或共享的成果,仍应及时 CopyFeatures 到文件地理数据库。
基本用法与代码模板
以下示例以 ArcGIS Pro 环境为参考,演示把中间结果放到内存、最终结果落盘的常见模式。
# -*- coding: utf-8 -*-
import arcpy
import time
# 环境配置
arcpy.env.overwriteOutput = True # 允许覆盖输出(谨慎使用)
arcpy.env.workspace = "in_memory" # 把当前工作空间设置为内存
# 输入与输出
in_fc = r"C:datatransport.gdbroads"
out_fc = r"C:dataoutput.gdbroads_buf_diss"
t0 = time.perf_counter()
# 1) 在内存中做缓冲
buf_fc = "roads_buf" # 因为 workspace= in_memory,可直接用名称
arcpy.analysis.Buffer(in_fc, buf_fc, "50 Meters", dissolve_option="NONE")
# 2) 在内存中溶解以减少冗余
diss_fc = "roads_buf_diss"
arcpy.management.Dissolve(buf_fc, diss_fc)
# 3) 最终结果落盘到文件地理数据库
arcpy.management.CopyFeatures(diss_fc, out_fc)
print(f"流程耗时:{time.perf_counter() - t0:.2f}s")
# 4) 清理内存中的中间结果(可选)
arcpy.management.Delete([buf_fc, diss_fc])
要访问内存中的对象,可用 in_memory/名称 的显式路径,或通过 arcpy.EnvManager 暂时切换工作空间:
# 显式路径写法
arcpy.Exists("in_memory/roads_buf")
# 上下文管理器写法,便于枚举删除
with arcpy.EnvManager(workspace="in_memory"):
for fc in arcpy.ListFeatureClasses():
arcpy.management.Delete(fc)
创建唯一临时名称与存在性检查
避免命名冲突是稳定自动化的关键。推荐结合 CreateUniqueName 与 Exists:
tmp_fc = arcpy.CreateUniqueName("tmp", "in_memory") # 自动生成不重复名称
arcpy.analysis.Buffer(in_fc, tmp_fc, "100 Meters")
if arcpy.Exists(tmp_fc):
cnt = int(arcpy.management.GetCount(tmp_fc)[0]) # 获取要素数量
print(f"临时要素数:{cnt}")
与数据访问模块(arcpy.da)的配合
在内存要素类上使用 arcpy.da 游标,可避免额外磁盘读写:
# 统计内存缓冲结果的面积总和(投影坐标系下)
total_area = 0.0
with arcpy.da.SearchCursor("in_memory/roads_buf", ["SHAPE@AREA"]) as cur:
for row in cur:
total_area += row[0]
print(f"缓冲区总面积:{total_area:.2f}")
性能对比的最小实验
下面给出一个可复现的“小基准”,比较 in_memory 与地理数据库输出的速度(以缓冲为例):
import time
import arcpy
arcpy.env.overwriteOutput = True
in_fc = r"C:datatransport.gdbroads"
# A) in_memory
t0 = time.perf_counter()
arcpy.analysis.Buffer(in_fc, "in_memory/roads_buf", "30 Meters")
t_inmem = time.perf_counter() - t0
# B) FileGDB
t1 = time.perf_counter()
arcpy.analysis.Buffer(in_fc, r"C:datascratch.gdbroads_buf", "30 Meters")
t_gdb = time.perf_counter() - t1
print(f"in_memory:{t_inmem:.2f}s, GDB:{t_gdb:.2f}s")
在典型机械盘或网络盘环境中,in_memory 往往有明显优势;SSD 上收益依然存在,但幅度会随数据量与工具类型而变化。
最佳实践与清理策略
- 只把中间结果放内存:可丢弃的数据放 in_memory,阶段性成果及时 CopyFeatures 到 GDB。
- 控制名称生命周期:用
CreateUniqueName或时间戳命名,避免覆盖与串扰。 - 显式删除:流程末尾
arcpy.management.Delete清理,长管线中分段清理降低峰值内存。 - 分块处理:超大数据按网格/行政区切块到内存处理,阶段成果落盘,再汇总。
- 失败兜底:异常时也要清理,结合 try/finally 确保 Delete 执行。
# try/finally 保障清理
tmp1, tmp2 = "in_memory/a", "in_memory/b"
try:
arcpy.analysis.Buffer(in_fc, tmp1, "100 Meters")
arcpy.management.Dissolve(tmp1, tmp2)
arcpy.management.CopyFeatures(tmp2, out_fc)
finally:
for ds in (tmp1, tmp2):
if arcpy.Exists(ds):
arcpy.management.Delete(ds)
常见问题与易错点
- 支持的数据类型:以要素类与表为主;对栅格数据集的直接写入通常不受支持(请落盘到 GDB/TIFF,或使用栅格对象工作流)。
- 路径写法:统一使用
in_memory/名称,或把arcpy.env.workspace设为in_memory后用短名。 - 会话生命周期:Python 进程结束即释放;ArcGIS Pro 崩溃或重启后内存数据不可恢复。
- 内存限制:32 位环境(如老版 ArcMap)受限更明显;64 位 ArcGIS Pro 更宽裕,但大数据仍需分块。
- 并行与多进程:ArcPy 通常不线程安全;若用多进程,每个子进程有独立 in_memory 命名空间,注意避免跨进程引用。
- OverwriteOutput:开启覆盖输出有助迭代,但要确保目标名不会被误覆盖关键数据。
- 投影与度量:涉及面积/长度计算前,先投影到合适的等积/等距坐标系,再在内存中计算。
典型场景选择建议
| 场景 | 是否优先用 in_memory | 备注 |
|---|---|---|
| 缓冲/叠置/选择等中间结果 | 是 | 链式操作快,减少 I/O |
| 最终成果产出/归档 | 否 | 落盘到 GDB 或企业级数据源 |
| 海量数据(> 数百万要素) | 视内存而定 | 建议分块,阶段性落盘 |
| 栅格分析 | 通常不适用 | 请使用栅格对象或文件输出 |
小案例:一次性分析脚本的“内存优先”重构
目标:对站点要素进行 300m 缓冲,求与地块相交面积,并输出 TOP10 结果。除最终表外,全部放在内存中进行。
# 输入
sites = r"C:projcity.gdbpoi_station"
parcels = r"C:projcity.gdbparcels"
out_table = r"C:projresult.gdbpoi_parcel_top10"
arcpy.env.overwriteOutput = True
arcpy.env.workspace = "in_memory"
# 1) 站点缓冲(内存)
buf = "sites_buf"
arcpy.analysis.Buffer(sites, buf, "300 Meters", dissolve_option="NONE")
# 2) 与地块相交(内存)
inter = "buf_parcel_inter"
arcpy.analysis.Intersect([buf, parcels], inter)
# 3) 计算相交面积(新增字段,内存)
arcpy.management.AddField(inter, "A_m2", "DOUBLE")
arcpy.management.CalculateField(inter, "A_m2", "!shape.area@SQUAREMETERS!", "PYTHON3")
# 4) 汇总每个站点的相交面积(内存)
stat_tbl = "stat_by_site"
arcpy.analysis.Statistics(inter, stat_tbl, [["A_m2","SUM"]], case_field="SITE_ID")
# 5) 选出 TOP10 并落盘
# 说明:内存表可作为 Select 工具输入,结果落盘到 GDB
top10_tbl = "top10"
arcpy.management.SelectLayerByAttribute # 占位说明:如需更复杂排序/取前N,可落盘后用 SQL 处理
arcpy.management.CopyRows(stat_tbl, out_table) # 简化:此处可替换为排序+取前N的具体实现
# 6) 清理(可选)
for ds in [buf, inter, stat_tbl, top10_tbl]:
if arcpy.Exists(ds):
arcpy.management.Delete(ds)
上例突出一个重构思路:把所有可丢弃的中间态留在内存,I/O 最后一跳再落盘。实际项目中可将“排序取前 N、字段派生”等逻辑进一步完善。
进阶建议:与 scratchGDB 搭配
当中间结果需要短暂持久化(例如跨会话复用、人工复核),可将关键阶段输出写入 arcpy.env.scratchGDB,其余仍留在 in_memory:
arcpy.env.scratchGDB # 系统临时地理数据库路径
key_stage = arcpy.CreateUniqueName("stage1", arcpy.env.scratchGDB)
arcpy.management.CopyFeatures("in_memory/roads_buf_diss", key_stage)
结语
总结来说,在 ArcPy 自动化中优先采用 in_memory 承载中间结果,是“既快又稳”的工程化选择:一方面显著减少 I/O 加速流程,另一方面通过命名规范与清理策略保证脚本结构清晰、资源安全。你在自己的项目里,最想把哪段“慢得让人抓狂”的流程改造成内存优先?欢迎留言交流,也可访问 GIS研习社(gisyxs.com)获取更多实践案例。
参考文献
- Esri. The in-memory workspace — ArcGIS Pro documentation. https://pro.arcgis.com/en/pro-app/latest/help/analysis/geoprocessing/basics/the-in-memory-workspace.htm
- Esri. Buffer (Analysis). https://pro.arcgis.com/en/pro-app/latest/tool-reference/analysis/buffer.htm
- Esri. Dissolve (Data Management). https://pro.arcgis.com/en/pro-app/latest/tool-reference/data-management/dissolve.htm
- Esri. Delete (Data Management). https://pro.arcgis.com/en/pro-app/latest/tool-reference/data-management/delete.htm
- Esri. CreateUniqueName (arcpy). https://pro.arcgis.com/en/pro-app/latest/arcpy/functions/createuniquename.htm
- Esri. Exists (arcpy). https://pro.arcgis.com/en/pro-app/latest/arcpy/functions/exists.htm
- Esri. ListFeatureClasses (arcpy). https://pro.arcgis.com/en/pro-app/latest/arcpy/functions/listfeatureclasses.htm
- Esri. Overwrite Output (Environment setting). https://pro.arcgis.com/en/pro-app/latest/tool-reference/environments/overwrite-output.htm
-
QGIS如何使用?新手入门必备操作清单(附:10个常用工具详解) 2026-03-15 08:30:02
-
零基础入门QGIS教程,新手如何安装配置?(附:插件清单与环境避坑指南) 2026-03-15 08:30:02
-
零基础入门QGIS教程:空间分析到底怎么学?(附:常用插件清单) 2026-03-15 08:30:02
-
QGIS坐标转换总是出错?五分钟掌握投影变换操作(附:参数对照表) 2026-03-15 08:30:02
-
QGIS新手导入数据总失败?盘点三种添加矢量栅格数据的高效方法(附:避坑清单) 2026-03-15 08:30:02
-
零基础入门GIS教程有哪些坑?避坑指南与必学核心技能盘点(附:快速上手路线图) 2026-03-15 08:30:02
-
QGIS操作手册太厚看不完?这篇精选核心功能速查表(附:快捷键大全) 2026-03-15 08:30:02
-
GIS教程电子书怎么找才靠谱?GIS研习社精选资源合集(附:独家下载通道) 2026-03-15 08:30:02
-
新手GIS开发怎么学?GIS教程书单与ArcGIS实战路线图(附:学习资源包) 2026-03-15 08:30:02
-
QGIS处理SIP数据总出错?核心插件与避坑指南(含:参数详解) 2026-03-15 08:30:01
-
QGIS中文界面怎么设置?新手入门必备操作手册(附:工具箱速查表) 2026-03-14 08:30:02
-
GIS自学从哪入手?零基础入门视频教程(含:软件安装包与练习数据) 2026-03-14 08:30:02
-
GIS自学从哪里开始?零基础入门必学这三大核心技能(附:软件安装包) 2026-03-14 08:30:02
-
自学GIS要多少天?从零到精通的学习路线图(附:4周速成计划) 2026-03-14 08:30:02
-
QGIS坐标转换总是失败?地理配准核心参数设置详解(附:参数对照表) 2026-03-14 08:30:02
-
QGIS二次开发遇到SIP模块编译失败?手把手教你配置环境(附:完整代码实例) 2026-03-14 08:30:02
-
QGIS安装卡在Python环境?手把手教你避开依赖库陷阱(附:完整安装清单) 2026-03-14 08:30:02
-
QGIS批量裁剪影像总是卡顿崩溃?老手教你用图形建模器自动化处理(附:工作流模板) 2026-03-14 08:30:01
-
QGIS零基础入门有多难?这份保姆级操作手册带你避坑(含:常用工具箱速查表) 2026-03-14 08:30:01
-
QGIS如何使用?新手入门必学5大核心功能(附:快捷键速查表) 2026-03-14 08:30:01