首页 编程与开发 ArcPy ArcPy入门学习指南(含:arcpy in_memory的详细解答)

ArcPy入门学习指南(含:arcpy in_memory的详细解答)

作者: GIS研习社 更新时间:2025-08-24 11:50:44 分类:ArcPy

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

ArcPy入门学习指南(含:arcpy in_memory的详细解答)

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)

创建唯一临时名称与存在性检查

避免命名冲突是稳定自动化的关键。推荐结合 CreateUniqueNameExists

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
相关文章