简介:面向GIS初学者及希望用Python扩展ArcGIS Pro的开发者,这份项目源码以简洁示例演示了在ArcGIS Pro中启动并固定Jupyter Notebook工作目录的完整配置方法。资源共3个文件,以inscode文件承载启动逻辑、HTML页面呈现说明,外加.gitignore用于版本管理;压缩包仅4KB,却覆盖了环境配置、目录设置与项目结构关键点。已有95人学习浏览,适合刚接触Jupyter交互式编程或想优化GIS工作流的用户。通过源码可掌握生成配置文件、修改c.NotebookApp.notebook_dir指定永久目录,以及直接从ArcGIS Pro的Python环境打开Jupyter到目标目录的操作思路;还能学习将Python脚本、软件包和源代码组织为可维护结构的方法,为后续空间数据分析、自动化批处理及GIS二次开发打下扎实基础。
1. 为什么要把jupyter notebook搬进ArcGIS Pro
我最早接触ArcGIS Pro时,其实有点抗拒里面内置的Python环境,总觉得命令行跑脚本就够了,没必要折腾notebook。直到有一次做土地利用变化分析,需要反复调整筛选条件、可视化中间结果,命令行那种“写完-运行-出bug-再修改”的循环让我效率极低,我才认真试了Pro自带的jupyter notebook,结果回不去了。
先说清楚这个组合解决什么问题。ArcGIS Pro的架构和旧版ArcMap最大的区别之一,就是Python被深度嵌入,你可以在Pro里直接打开notebook,连arcpy的导入和环境配置都省了。这时候你面对的不仅是一个代码编辑器,而是一个能边写边跑、边跑边看地图的交互环境。对于做数据分析、批量处理、方法验证的人来说,这种“即时反馈”是纯脚本难以替代的。
那“项目源码”这一块怎么理解?我个人的习惯是:把一套完整的分析流程拆成若干cell,从数据读取、字段计算、统计汇总到结果导出,每一步都有对应的可执行代码。这样不仅自己能复用,团队协作时别人也能快速看懂你的分析脉络,比一堆孤立脚本好维护得多。
适合谁?三类人最有必要看这篇文章:
- 正在从ArcMap迁移到Pro的老用户,不太适应新环境的Python工作流。
- 做地理数据处理、空间分析的研究人员,需要快速验证方法。
- 想用Python批处理代替手工重复操作的Pro用户,但不知道从哪下手。
这篇文章不是简单的“打开notebook”教程,我尽量把我踩过的坑、验证过能跑的代码、以及排查问题的思路都写出来,你跟着走完一遍,应该就能独立搭起自己的notebook分析环境了。
2. 环境与界面:先搞清你手上有什么工具
2.1 ArcGIS Pro的Python环境到底是怎么回事
很多人在第一步就卡住,是因为没搞懂Pro的Python环境跟普通Python环境的区别。ArcGIS Pro 2.x以上版本,安装时会自带一个独立的conda环境,默认叫arcgispro-py3。这个环境里有arcpy、numpy、pandas这些常用库,而且版本是Esri官方测试过的,跟Pro的内核深度绑定。
这意味着什么?如果你自己拿Python官网的安装包或者Anaconda另建环境,直接pip install arcpy是不行的,arcpy并不在PyPI上提供独立安装包。所以最省心的方式是,所有跟Pro相关的Python工作,都直接用Pro自带的这个环境。你可以在Pro界面内打开notebook,也可以在Pro安装目录下找到python.exe,然后通过命令行启动jupyter。
我自己习惯的做法是直接点Pro界面顶部的“分析”选项卡,然后选择“Python”,Pro会打开一个内嵌的notebook窗口,不需要额外配置任何东西。首次打开会稍微慢一点,因为要初始化内核,之后就好很多了。
2.2 两种打开notebook的路径,各自怎么选
具体来说,打开方式我整理成下面几种:
- 在ArcGIS Pro里:分析 -> Python。适合日常交互分析,跟地图联动最方便。
- 在Windows命令行:进入
C:\Program Files\ArcGIS\Pro\bin\Python\envs\arcgispro-py3,运行python -m jupyter notebook。适合需要自定义工作目录、或者没开Pro界面但想跑脚本的场景。 - 通过ArcGIS Pro的包管理器,给arcgispro-py3环境单独装一个
jupyterlab,这样你可以用更现代一点的notebook界面。
平时我推荐第一种。因为Pro内置的notebook跟地图文档是关联的,你在notebook里执行arcpy操作后,Pro的目录、地图内容能实时刷新,调试时特别爽。
2.3 一个容易被忽略但很关键的细节:工作路径
真正用起来以后,有一个细节我建议你特别留意——工作路径。Pro内置notebook的工作目录默认跟项目工程(.aprx)所在的目录保持一致,但你不是总能记得当前目录到底在哪。我有一次跑了半天代码,导出结果后发现文件跑到工程文件旁边去了,一时没找到,还以为是代码写错了。
所以每次新建notebook,我的习惯是第一行就先打印当前路径,顺便把工作空间设置好。比如:
import os print(os.getcwd()) import arcpy arcpy.env.workspace = r"C:\Users\你的用户名\Documents\ArcGIS\Projects\你的工程名" arcpy.env.overwriteOutput = TrueoverwriteOutput = True这个设置也很重要。arcpy默认不允许覆盖已有数据,如果你重复跑同一段分析,会直接报错说数据已存在。开了这个开关后,就不用来回删中间数据了。
3. 项目实战:从要素类读取到面积统计的完整源码
3.1 案例背景:为什么拿面积统计来说事
面积统计算是最常见也最容易被轻视的需求。比如我手头有一个地块要素类,里面有不同类型的用地,领导往往就一句话:“把每种类型的面积算一下,保留两位小数。”听起来简单,但实际做起来,数据量大、字段类型杂、坐标系不同导致的面积单位不一致,都是坑。
尤其是“只保留小数点后两位”这个点,热搜里也出现了,说明很多人被这个细节折磨过。直接round()只能管住Python里的数值显示,但保存到属性表或者导出成表格,格式可能又被“打回原形”了。我会在下面的代码里用两种方式处理,一种是用Python格式化,另一种是用字段计算器写到目标字段。
3.2 完整代码:使用SearchCursor做属性统计
我先写一个不需要安装任何第三方库、直接用arcpy内置功能就能跑的代码。需求是统计某个小班图层里不同地类代码的面积,并格式化输出。
# -*- coding: utf-8 -*- import arcpy fc = r"C:\data\land_use.gdb\land_parcels" type_field = "LAND_CODE" area_field = "SHAPE@AREA" stats = {} with arcpy.da.SearchCursor(fc, [type_field, area_field]) as cursor: for row in cursor: code = row[0] area = row[1] if code not in stats: stats[code] = 0.0 stats[code] += area print("统计结果(原始平方米):") for code, total_area in stats.items(): print(f"地类代码 {code}: {total_area:.2f} 平方米")这段代码的底层的逻辑是:游标逐行扫描要素类,把相同地类代码的面积累加在一起。SHAPE@area是arcpy里获取要素几何面积的固定写法,不需要你自己再算投影。值得注意的是,这个面积是要素本身存储的坐标系下的面积,如果图层是WGS84经纬度,算出来不是平方米而是度,这点后面会细说。
3.3 保留两位小数的正确姿势
如果你只是想在notebook里看着好看,那么用f-string格式化就够了,就像上面那样。但如果想把结果更新回到数据里,或者输出成Excel表格,就要小心了。
我常用的一种方式是用arcpy.management.CalculateField配合Python表达式:
arcpy.management.AddField(fc, "AREA_SQKM", "DOUBLE") arcpy.management.CalculateField( fc, "AREA_SQKM", "round(!SHAPE.area@SQUAREKILOMETERS!, 2)", "PYTHON3" )这里用到了!SHAPE.area@SQUAREKILOMETERS!这种字段表达式,可以直接在字段计算里做单位换算并保留两位小数。在notebook里跑完之后,记得刷新一下图层属性表,看看计算结果是不是符合预期。我第一次用这个语法时,忘了加@SQUAREKILOMETERS后缀,结果面积数值全部变成平方米,跟预期的千差万别,排查了好一会儿才发现。
3.4 更实用的批量处理场景:按属性分组统计并导出
上面只是单要素类的统计。实际工作中,我经常需要对多个要素类做同样的一套分析,比如不同年份的用地数据,每年跑一遍。这时候我就会把代码封装成函数,然后用循环目录的方式批量处理。
import arcpy import os gdb = r"C:\data\years_data.gdb" output_txt = r"C:\data\area_stats.txt" with open(output_txt, "w", encoding="utf-8") as f: for year in range(2018, 2024): fc = os.path.join(gdb, f"land_use_{year}") if not arcpy.Exists(fc): print(f"{year}: 要素类不存在,跳过") continue stats = {} with arcpy.da.SearchCursor(fc, ["TYPE", "SHAPE@AREA"]) as cursor: for row in cursor: stats[row[0]] = stats.get(row[0], 0.0) + row[1] f.write(f"===== {year} =====\n") for typ, area in stats.items(): f.write(f"{typ}: {area:.2f}\n") print("批量统计完成,结果已写入:", output_txt)这里用arcpy.Exists先判断要素类存在与否,避免中间某年数据缺失导致整个流程中断。输出到txt而不是直接print,好处是结果不容易丢,notebook一旦关闭,print的内容就没了,但文件还在,这个经验也是我跑长任务时被坑出来的。
4. 常见问题与排查技巧实录
4.1 jupyter notebook安装报错:subprocess-exited-with-error
这个词条在热搜里出现了,我猜是很多人尝试在conda环境里装jupyter或装扩展包时遇到的。
subprocess-exited-with-error这串错误,本质上是pip在安装某个包时,触发底层编译或子进程执行,但子进程以非零状态结束。常见原因有几个:一是包版本和Python版本不兼容,二是缺少Microsoft C++ Build Tools,三是网络问题导致下载的包损坏。
先说最简单有效的解法:尽量不要自己去折腾pip install jupyter。ArcGIS Pro默认环境已经包含notebook模块,直接打开分析选项卡就能用。如果你确实想要jupyterlab,或者需要安装扩展包,建议用Pro内置的“Python包管理器”,它底层是conda,能自动处理依赖关系,比直接pip稳得多。
如果你还是想用pip,遇到报错时可以先加--no-cache-dir参数重试,排除缓存导致的下载文件损坏问题:
python -m pip install jupyterlab --no-cache-dir如果还是不行,就去看完整的错误日志,注意看最后面有没有error: command 'gcc' failed或者Microsoft Visual C++ 14.0 is required这类提示,前者表示缺编译工具,后者很明确就是缺C++运行库。解决办法就是安装Visual C++ Build Tools,我个人的经验是,装好之后重启一下Pro和命令行工具,基本能解决。
4.2 notebook能打开,但代码运行一直卡住不输出
这个问题我碰到过不止一次。症状是点击运行cell之后,In [*]一直显示,但结果迟迟出不来,代码看起来也没死循环。
先排查是不是数据量太大。arcpy处理上百万条记录时,SearchCursor逐行扫描确实需要时间,但这通常不至于卡死。如果卡了很久,多半是网络盘文件访问、或者图层坐标系操作时触发了几何网络计算,这种场景我在Shapefile转GDB时遇到过几次。
一个有效的排查技巧是:在notebook里新建一个cell,只跑print(1),看看内核是否还活着。如果print(1)瞬间有输出,说明内核正常,问题出在具体代码上;如果连print(1)都没反应,说明内核已经死了,直接重启kernel吧。
4.3 导入arcpy失败:ModuleNotFoundError
这也是新手最容易出现的错误。你在notebook里写import arcpy,结果报错说找不到arcpy,第一反应往往是“我装的Python有问题”。其实十有八九是用的Python环境不对。你当前notebook的kernel如果选的是base(Anaconda自带的那个环境),那里面当然没有arcpy。
解决办法是:在notebook界面里点一下右上角的kernel名称,确认当前内核是不是arcgispro-py3。如果你是命令行方式启动的jupyter,一定要从Pro安装目录下的那个python.exe启动,而不是系统盘里的Python。
我自己长期用下来,姿势是:直接从Pro的“分析”选项卡打开notebook,这样环境永远不会选错。如果非要命令行启动,也要先激活环境,这一步省不得,省了后面全是坑。
4.4 面积统计结果看起来不对:坐标系问题
前面的代码提到了面积单位受坐标系影响。这里单独展开说,因为我见过不少人在这上面栽跟头。如果你的要素类存储坐标系是WGS84经纬度,那么SHAPE@AREA返回的面积单位是平方度,不是平方米。平方度是一个随纬度变化很大的单位,无法直接用来做面积统计。
解决办法是在统计之前,用arcpy.management.Project把数据投影到合适的投影坐标系。如果是全国范围的分析,用Albers等积投影;如果是省级或者市级,用对应的高斯-克吕格投影更好。
wgs84 = arcpy.SpatialReference(4326) albers = arcpy.SpatialReference(102025) # Asia North Albers Equal Area Conic fc_projected = r"C:\data\land_use_projected.gdb\land_parcels" arcpy.management.Project(fc, fc_projected, albers)跑完投影后再用前面的统计代码,面积数值才是一致可比的。这个步骤虽然多了一道工序,但能保证后续不管是面积统计还是空间分析,结果都站得住脚。
5. 把notebook工程化的几个建议
5.1 善用markdown cell,把分析思路写下来
很多人用notebook只写代码,markdown cell基本不用。但我觉得这是最大的浪费。在每段分析前面用markdown写清楚这段代码的输入是什么、输出是什么、为什么这么做,回头再来看的时候,或者别人拿你的notebook去复现的时候,都会轻松非常多。
我自己的notebook通常长这样:
- 标题和日期、数据来源
- 数据预处理思路
- 每个步骤的代码块,前面配上简单的说明
- 最后的结论和备注
这种做法在其他领域可能叫“可复现研究”,放到GIS项目里同理,非常实用。
5.2 封装常用操作,慢慢积累自己的工具库
写多了你会发现,很多代码是在重复的。比如读取GDB里的要素类、统计字段、批量导出图片,这些操作每次写一遍语法很麻烦。我建议把常用功能封装成my_gis_tools.py,放在固定的路径下,notebook里每次只需要:
import sys sys.path.append(r"C:\code\utils") import my_gis_tools as mgt mgt.area_stats(fc, ["TYPE"], unit="km2")这样即使用户换了新电脑、新项目,代码依然能快速复用。这也是把零散的notebook脚本往“项目源码”方向沉淀的做法。
5.3 一万次脚本运行后的提醒:定期保存、导出备份
notebook本身有自动保存功能,但有一次Pro异常崩溃后,我发现新建的cell内容没完全恢复,丢失了一点分析记录。后来我每完成一阶段分析,就主动用File -> Export把notebook导出为.py文件或HTML备份一份。这样即使Pro出问题,我的分析逻辑和代码都还在,顶多重新跑一遍,不至于从头再来。
另外,如果脚本里涉及重要的中间数据,建议在开头就集中定义路径,不要裸写一堆硬编码路径在代码里。好的习惯是:
RAW_DATA = r"C:\data\input" GDB_PATH = r"C:\data\result.gdb" TEMP_DIR = r"C:\data\temp"需要改路径的时候只需要改一处,方便维护,也避免后面自己都忘了哪个文件是哪来的。
6. 实操心得:我踩过最深的三个坑,你在代码里要注意
上述内容已经写了不少,最后说三个最实际的经验吧。
第一个坑是环境变量冲突。去年我用的Pro还是2.9版本,系统的Path变量里同时配了Anaconda的Python和Pro的Python,结果命令行启动jupyter时经常加载错环境。折腾了半天,最后是把Anaconda从Path里临时移除,或者直接双击Pro安装目录下的python.exe进入交互模式,才彻底绕开这个问题。如果你机器上也装了多套Python,这一点千万要留意。
第二个坑是字段名大小写和中文编码。notebook里输入要素类字段名时,我建议直接用arcpy的ListFields提前打印一下真实字段名,不要凭印象敲。尤其是从Excel转过来的数据,字段名经常自动变成F1、F2,不检查的话你后面所有代码都会跑偏。输出中文时要注意csv/txt的编码,写文件时用encoding="utf-8-sig"而不是"utf-8",这样用Excel打开csv时中文才不会乱码,这个细节我调试过多回才记住。
第三个坑是长时间运行的notebook会内存膨胀。如果你在一个cell里反复创建大数据集的几何对象,内存占用会一直涨。我建议处理完一批数据后,主动把不需要的dataframe或大列表清掉,用del变量名释放一下。虽然Python有自动垃圾回收,但GIS数据的底层对象并不总是立刻释放,跑批任务时你就知道这个习惯有多重要了。
其实ArcGIS Pro里跑jupyter notebook并不神秘,它就是一个有地图联动能力的Python交互环境。但正因为Pro把环境和工具都准备好了,你反而更要知道背后的原理、路径和边界在哪里。拿这套环境跑通一个完整的小项目,从数据读取到统计导出走一遍,你就会发现很多以前要手工处理的流程,现在几段代码就能搞定。
本文还有配套的精品资源,点击获取