简介已编译的 GDAL地理空间数据抽象库gdal111 库包是一套面向地理信息开发者和数据分析师的预编译工具集省去源码编译的环境配置和等待时间可在 Windows 系统内直接集成使用。整个资源仅 3.46MB共含 241 个文件按 lib、include、bin、data、html 五个目录组织lib 中提供程序运行所需的 DLL 与静态库include 内包含 72 个 C 头文件用于二次开发bin 下提供 22 个可直接执行的命令行工具data 里放置 28 个 CSV 坐标参数与格式定义文件另有 89 个 HTML 离线文档与少量矢量样例文件。已有 297 人学习属于经验证可用的成熟版本。借助 bin 目录中的 gdal_translate、ogr2ogr 等程序可以完成栅格裁剪、投影转换、矢量合并等高频操作结合头文件、离线文档和坐标参数文件开发者能快速编写读写 Shapefile、GeoJSON、TIFF 等多种格式的代码应用于遥感影像预处理、空间数据整理以及轻量级 GIS 项目开发。1. 别急着编译 GDALgdal111 预编译包解的是什么问题前两天我帮人迁移一台跑测绘脚本的老机器Python 还是 2.7代码里全是osgeo.gdal的调用pip 装新版 GDAL 直接报找不到匹配版本。折腾到最后反而是「已编译的 GDAL gdal111」这种最笨的办法救了场——把别人用 Visual Studio 编译好的 GDAL 1.11 二进制包下载下来配好环境变量十分钟跑通。这篇笔记就是讲清楚这条路gdal111 是什么、为什么现在还有人非它不可、怎么在 Windows 上把它配成一个独立可用的 GDAL 环境以及我在这个过程中踩过的那些坑。如果你也在维护老系统或者被某个旧插件锁死在 GDAL 1.11这篇应该能帮你省掉一下午。2. 为什么非要 gdal111预编译包的构成与选型逻辑2.1 预编译包都装了什么Exe、DLL 和数据文件先拆一下「已编译」这三个字。很多人用 GDAL 是从pip install GDAL或 conda 开始但那是新世界。在老环境里GDAL 通常以「绿色压缩包」形式存在解压后是一个包含bin、gdal-data、plugins等子目录的文件夹。bin 里有gdal111.dll、gdal_translate.exe、gdalinfo.exe、ogrinfo.exe这些命令行工具以及 geos、curl、sqlite 等依赖 DLLgdal-data 里是gcs.csv、pcs.csv、datum等坐标系统数据文件某些包还会带上 Python 扩展的osgeo目录里面有_gdal.pyd和一堆.py文件。这套结构和源码编译出来的结果几乎一样区别在于别人已经把编译环境、依赖头文件、链接库的排列组合全部替你处理完了。你不需要装 Visual Studio不需要手动编 proj、geos、curl也不需要对着 CMake 报错发呆。对大多数只调 API 的从业者来说这个「已编译」的价值被严重低估了。2.2 gdal111 为什么到现在还有人找接口与数据行为差异有人会问直接用 GDAL 3.x 不行吗如果是从零开始的新项目我会直接说不行也得行新版是唯一选择。但如果你的业务锁在某个老 GIS 插件、某个 Python 2.7 遗产工程或者一套基于 1.11 时期的 VRT 模板上那 gdal111 就不可替代。关键差异有几个。第一坐标系统数据库格式不同1.11 时代靠gcs.csv和pcs.csv查投影GDAL 2.x 后期到 3.x 已经完全转向 proj.db很多老数据里的投影描述在 3.x 下会被识别成未知坐标系甚至反过来影响几何输出。第二某些驱动的加载行为不同老版本默认支持的格式列表和新版不一样ECW、MrSID 这类商业驱动在新版要么砍掉要么插件化老包反而能直接用。第三API 细节差异1.11 的osr.SpatialReference没有后来加的那些坐标轴顺序逻辑老代码里写好的投影转换在新版可能结果一致也可能差 0.01 度。这种事没法靠文档穷举只能用版本锁死。2.3 32 位还是 64 位跟着解释器走别跟着操作系统走这是 gdal111 选型里最容易翻车的一步没有之一。判断标准不是你的 Windows 是 64 位还是 32 位而是你要调用 GDAL 的那个 Python 解释器是几位的。64 位系统上装 32 位 Python 非常常见尤其是老项目的运维环境你很少动它。下载预编译包时看到win32和win64字样不要想当然选 win64。先在你的命令行里跑一下python -c import platform,sys; print(platform.architecture()[0], sys.version)输出长这样64bit 2.7.18 (v2.7.18:5242a47, Apr 15 2019, 09:29:16)前面是64bit就去下载 win64 的 gdal111要是32bit老老实实选 win32 的包。这个选择影响的不只是性能而是能不能import osgeo的问题。64 位 Python 加载 32 位编译的_gdal.pyd时Windows 加载器会直接拒绝表现是报错甚至是进程闪退没有任何友好提示。2.4 支持网站选包的三个判断依据搜索「已编译的 GDAL gdal111」时你会看到几个老牌支持网站最有名的是 gisinternals这类站专门提供编译好的 GDAL 二进制和配套开发包。选包时我一般看三点。第一看版本标签目录名里通常写得很清楚比如带gdal111的路径就是你要的 1.11 系列别下成gdal110或者gdal112。第二看位数和 Python 版本标记常见命名里会出现x86/x64、py27/py34这类字样分别对应 32 位、64 位和 Python 2.7、Python 3.4这是选包的核心依据。第三看页面说明里的配套运行库尤其是「VC 运行库」提示——老版本包通常对应 Visual Studio 2008/2010/2013 时代的编译环境缺运行库的话后面会多出十几个 DLL 报错。下载回来不要急着解压到随意位置接下来这一步直接决定你后面会不会陷入 DLL 地狱。3. 安装与配置把 gdal111 变成默认 GDAL 环境3.1 动手前确认 Python 位数一个代码块的事我接手的每个老环境都会先做一次「体检」确认三件事Python 版本、Python 位数、当前 PATH 里有没有别的 GDAL。前面那个命令已经拿到了位数和版本再补一个检查 PATH 里是否存在旧 GDALwhere gdalinfo如果输出提示找不到说明当前环境还没有被其他 GDAL 污染这是最理想的情况。如果输出了一个路径比如 C:\QGIS\bin\gdalinfo.exe说明你的 PATH 里已经存在别的版本后面配置时要特别小心顺序问题。这一步做 30 秒却能省掉后面 30 分钟的排错时间。3.2 目录规划与解压路径里不要有空格解压目录看起来是小事但 gdal111 年代的工具链对路径字符的处理远不如新版健壮。有些命令行工具在解析带空格的路径时会断掉有些 Python 绑定在加载配置文件时也会因为路径中间的空格出诡异问题。所以我的习惯是统一解压到根目录下的短路径比如C:\gdal111。解压完成后先确认目录结构是否完整。至少要看到bin和gdal-data这两个文件夹C:\gdal111dir如果列目录的结果里有bin、gdal-data并且 bin 下能看到gdal111.dll和gdalinfo.exe恭喜这个包是完整的。有的发布包把数据文件放在bin\gdal-data下也有的放在根目录位置不同而已关键是你能找到它。找不到gdal-data的包后面投影读取一定会出问题宁可重新下载一个也别将就。3.3 环境变量配置GDAL_DATA 与 PATH 的顺序环境变量是整个 gdal111 能不能用起来的核心顺序是先设GDAL_HOME和GDAL_DATA再改 PATH。在命令行里先用临时变量验证跑通了再写入系统环境变量。临时变量在当前窗口生效适合快速验证不用重启set GDAL_HOMEC:\gdal111 set GDAL_DATAC:\gdal111\gdal-data set PATHC:\gdal111\bin;%PATH%三条命令的含义分别是GDAL_HOME给工具链一个基准目录GDAL_DATA让 GDAL 能找到坐标系统数据文件PATH 前面追加的bin目录保证命令行工具优先加载这个版本的 DLL。PATH 的顺序至关重要——只有把C:\gdal111\bin放在最前面gdalinfo才会命中你的老版本而不是系统里某个新版本的入口。用临时变量跑通后再通过系统属性里的「环境变量」对话框持久化三个值照抄即可。提示不要用setx PATH来追加路径它会把变量值重新写入超过 1024 字符时直接截断你已经配过的其他软件路径全会丢。这是血泪经验。3.4 Python 绑定PYTHONPATH 与 site-packages 两种做法命令行工具能跑了Python 还要单独配。gdal111 时代的 Windows 发布包通常把 Python 绑定放在一个叫bindings或类似名字的目录里里面有一个osgeo文件夹包含gdal.py、ogr.py、osr.py和编译出来的_gdal.pyd。让 Python 找到它有两条路。第一条路是设置PYTHONPATH指向绑定目录set PYTHONPATHC:\gdal111\bindings然后验证python -c from osgeo import gdal; print(gdal.VersionInfo())输出1110000之类的数字串就说明绑定生效了。这条路的好处是环境隔离不污染 Python 的 site-packages以后不用了把环境变量删掉即可。第二条路是把osgeo文件夹整个复制到 Python 安装目录下的Lib\site-packages里一劳永逸但切换版本时容易留下残留文件。我个人的习惯是优先用PYTHONPATH因为老机器上有时候一个 Python 解释器要服务多套项目环境变量隔离比文件复制干净得多。配好之后命令行里再跑一次python -c from osgeo import gdal; print(gdal.VersionInfo())如果不再报错说明 Python 通道也通了。4. 验证环境命令行与 Python 双通道确认 gdal111 生效4.1 命令行通道gdalinfo --version 与 where gdalinfo很多人配置完环境变量就急着跑业务脚本结果报错一堆回头才怀疑是版本没生效。验证的动作必须在第一时间做而且要做两层。第一层是查路径来源第二层是查实际版本。where gdalinfo这条命令会列出 PATH 里所有能命中的gdalinfo第一个就是会被实际调用的那个。确认它输出的是C:\gdal111\bin\gdalinfo.exe就说明 PATH 顺序没有错。接着gdalinfo --version如果输出类似GDAL 1.11.5, released 2016/06/24的字符串说明这个工具确实是 1.11 系列。有些机器上 PATHT 前面还残留着别的 GDAL 目录你配了环境变量也白搭--version会直接揭穿。这一层验证不通过后面全是在错误版本上做调试。4.2 Python 通道from osgeo import gdal 打出版本命令行通过了不等于 Python 能通过因为 Python 绑定是独立编译的扩展模块依赖的 DLL 加载路径和命令行工具不完全一样。Python 这边要验证的不只是版本还要确认扩展加载时能找到gdal111.dll。写一个小脚本一次性验证from osgeo import gdal, ogr import sys print(Python:, sys.version) print(GDAL:, gdal.VersionInfo()) print(OGR:, ogr.GetVersion()) print(Drivers:, gdal.GetDriverCount())逻辑说明gdal.VersionInfo()返回的是数字版本号比如1110000代表 1.11.01110500代表 1.11.5ogr.GetVersion()用来验证另一个子库gdal.GetDriverCount()返回的是当前注册的栅格驱动数量老版本全功能包一般在 100 个以上如果这个数字是十几说明驱动没加载全多半是依赖 DLL 缺失或者插件目录没指对。这个脚本也是后面判断环境损坏时的首要排查工具。4.3 跑一条真实数据通路gdal_translate 转 PNG验证环境不能只停留在打印版本号还得跑一条真实数据流。最省事的测试是用gdal_translate把一个 tif 转成 PNG中间涉及打开驱动、读取栅格、写入新格式三个关键环节gdal_translate -of PNG -outsize 800 800 C:\data\input.tif C:\data\output.png参数说明-of PNG指定输出格式-outsize 800 800把输出缩放到 800×800 像素适合快速测试如果测试用的栅格比较大这个参数能避免写出一个大文件。执行成功后再去查一下输出文件的元数据确认它真的是 PNG 且空间参考没丢gdalinfo C:\data\output.png如果gdalinfo输出的坐标系统信息是你这张图的原始投影比如某度带的高斯投影说明从读入到写出整个链路没问题。如果显示Coordinate System is后面是空的说明数据文件或投影数据库没被正确加载回到上一章查GDAL_DATA。4.4 校验投影读取GDAL_DATA 是否真的生效栅格通路过了还要专门验证投影解析。很多老数据的投影写得很古老比如 ESRI 风格或 FGDC 格式的 WKT新版 GDAL 不一定认识而 gdal111 配好 GDAL_DATA 后通常能正确读出。用 Python 脚本验证更直观from osgeo import gdal, osr ds gdal.Open(rC:\data\input.tif) wkt ds.GetProjection() print(Raw WKT:, wkt[:120]) srs osr.SpatialReference() srs.ImportFromWkt(wkt) auth srs.GetAuthorityCode(PROJCS) or srs.GetAuthorityCode(GEOGCS) print(EPSG:, auth)逻辑说明GetProjection()拿到的原始 WKT 是最可靠的判断依据如果它是空的说明 GDAL 压根没读到投影信息ImportFromWkt()把 WKT 转成SpatialReference对象再通过GetAuthorityCode()尝试映射 EPSG 编号。GDAL_DATA 配置正确时这段脚本大概率能打印出 EPSG:xxxx 的结果如果打印None优先检查环境变量里GDAL_DATA的值是否指向真实的gdal-data目录这是老版本投影问题里最常见的原因不存在玄学。5. gdal111 的常见坑从 DLL 报错到版本抢路5.1 ImportError: DLL load failed先查 VC 运行库再查 PATH现象from osgeo import gdal时报ImportError: DLL load failed而且错误信息里只告诉你导入失败不给具体缺失的 DLL 名。很多人在这一步就开始怀疑包坏了反复重下。原因这基本是两个原因之一。一是缺少编译器运行库gdal111 时期的预编译包对应不同版本的 Visual C Redistributable缺了它gdal111.dll虽然还在但加载器找不到它依赖的msvcr*.dll整个导入就失败了二是 Python 绑定目录里依赖的 DLL 没有出现在 PATH 中因为有些包的_gdal.pyd是按相对路径找 DLL 的你的 PATH 里没有 gdal111 的 bin 目录它就找不到。解决先装对应年代的 VC 运行库这是最大概率的修复手段然后确认PATH里确实有C:\gdal111\bin且在当前进程里已生效重新打开一个命令行窗口再试别用旧窗口最后用dumpbin /dependents或者Dependencies工具查一下_gdal.pyd的依赖项看具体缺哪个文件。按这个顺序排查百分之九十九能救回来。5.2 64 位 Python 配 32 位 gdal111加载器直接拒绝连报错都不给现象环境变量全配好了命令行 gdalinfo 正常但 Python 里一import osgeo就闪退或者报ModuleNotFoundError有时候干脆是一个没有任何输出的进程崩溃。这是最让人摸不着头脑的一类问题。原因平台位数不匹配。64 位 Python 进程加载 32 位 DLL 时Windows 的模块加载器会拒绝但不是所有状态下都会弹出友好的错误窗口在某些 Python 发行版里这个过程表现为进程无提示退出。命令行 gdalinfo 能跑是因为它本身就是对应位数的 exe和 Python 加载器不是一回事。解决回去执行python -c import platform; print(platform.architecture()[0])拿到解释器位数按这个位数重新下载对应 gdal111 发布包。没有别的技巧位数错了换包没有转化方案。5.3 PATH 里新版 GDAL 先抢位gdalinfo 版本对不上现象配好环境变量后gdalinfo --version输出的却是GDAL 3.x或者where gdalinfo显示路径不在C:\gdal111。你明明已经设置了 PATH但就是轮不到这个包。原因Windows 的 PATH 是按顺序查找的前面有其他软件QGIS、FWTools、anaconda写入的 GDAL bin 目录你的C:\gdal111\bin加在了它们后面那执行的永远是先被找到的那个。还有一个隐藏点是很多安装在系统级别的软件把自己的目录写在了「系统变量」的 PATH 里而你改的是「用户变量」的 PATH系统变量的优先级在用户变量之前。解决在「系统属性 → 环境变量」里同时查看用户变量和系统变量的 PATH。如果有冲突把C:\gdal111\bin挪到用户变量 PATH 的最前面不够的话直接把它提到系统变量 PATH 的首位。改完以后用where gdalinfo验证第一条命中路径。如果你不想动全局 PATH更稳的方案是最后一张里说的启动脚本隔离法。5.4 GDAL_DATA 缺失投影全部变成 Unknown现象命令行工具看起来一切正常但gdalinfo输出的坐标系统是空的或者 Python 里GetProjection()返回空字符串矢量数据无法正确输出投影用gdalwarp重投影时指定了 SRS 却报「unable to find datum」。原因环境变量GDAL_DATA没有设置或者指向的目录里没有gcs.csv。gdal111 的投影解析不靠任何内置数据库它在运行时去GDAL_DATA目录里翻 csv 文件。这个变量丢了所有投影解析功能集体失效。新版 GDAL 对这类错误有更好的兜底老版本直接摆烂看起来就像「装好了但功能残废」。解决找到解压目录下的gdal-data文件夹设置GDAL_DATA指向它然后重启所有命令行窗口和 Python 进程。注意 Python 里 osgeo 在import时读取环境变量所以修改后必须重新启动进程在同一个 Jupyter notebook 里改了是没用的。5.5 想在 Python 3.8 上用 gdal111能装上也不建议用现象下载了一个 gdal111 预编译包Python 是 3.9把osgeo目录复制到 site-packages 之后import osgeo直接报ImportError: DLL load failed或者干脆报版本不兼容的错误。原因gdal111 时代的 Python 绑定是按当时 Python 的 C 扩展 ABI 编译的主版本不同、小版本跨度太大扩展模块和解释器之间的二进制接口对不上。这不是设置能解决的是编译期就决定了的事。旧包对应的 Python 范围通常以 2.7 或 3.4 为主3.8 以后基本找不到官方预编译版本。解决用匹配老绑定年代的 Python 解释器最稳妥的组合是 Python 2.7 配 64 位 gdal111或者 Python 3.4 配对应包。如果新 Python 环境里想用 GDAL 功能正确做法是使用新版 GDAL 的 wheel而不是逆向兼容。老代码实在离不开 1.11 API 的话建议直接上一台虚拟机或者 Docker 容器跑 Python 2.7别在当前机器硬刚。6. 把 gdal111 做成本地绿色环境隔离与共存技巧6.1 一个 bat 启动器解决 PATH 污染全局 PATH 里塞一个老版本 GDAL早晚会影响其他软件。我的做法是给 gdal111 单独做一个启动器脚本需要时打开不需要时完全不干扰系统环境。新建一个gdal111.bat内容如下echo off set GDAL_HOMEC:\gdal111 set GDAL_DATAC:\gdal111\gdal-data set PATH%GDAL_HOME%\bin;%PATH% cmd /k逻辑说明set只对当前进程和子进程生效不改系统环境变量进程关了环境就还原cmd /k会在这个环境里打开一个新的命令行窗口你在里面跑gdalinfo和python用的都是老 GDAL。这个 bat 相当于一个绿色环境入口双击它进去就是 gdal111 的环境关掉窗口原来的 PATH 原封不动。这是我在吃了很多次 PATH 污染的亏之后总结出的后悔药——重装 QGIS 或 Anaconda 再也不用担心被老版 GDAL 顶掉。6.2 同机共存新旧两套 GDAL 的调用习惯如果你在同一台机器上还要用新版 GDAL 做别的项目两个版本共存的关键是别让全局变量里出现任何一个版本的 PATH 硬编码。新版 GDAL 靠 venv 或 conda 环境管理老版 gdal111 靠上面的 bat 入口。两个环境永远不互相出现在对方的 PATH 里。实际调用时老项目先双击gdal111.bat在里面跑 Python 脚本系列化任务我习惯在外部 Python 里通过subprocess调用转换好的gdal_translate.exe绝对路径这样既能避免 DLL 冲突又把老工具的核心能力留在了新版生态里。我已经把这个 bat 作为固定手段用了很久凡是碰老式 S57 数据和旧投影定义进这个环境里处理起来几乎没有意外出了这个环境系统里是干干净净的现代工具链。这套思路希望帮到你少走一点我当时绕的弯路。本文还有配套的精品资源点击获取