ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Win7+Python2.7安装GDAL全记录:DLL加载失败与环境变量是最终难题

Win7+Python2.7安装GDAL全记录:DLL加载失败与环境变量是最终难题

简介:面向Python 2.7用户在Win7 64位平台安装GDAL的完整实操记录,适合GIS、遥感领域需要搭建GDAL Python开发环境的初学者参考。文档围绕两种安装路线展开:一是通过GDAL core自带swig/python进行编译安装,二是直接下载官方msi文件快速安装;均给出具体命令、依赖环境说明与配置步骤,并重点剖析了常见的swig.exe未安装、VS2010环境变量缺失、ImportError DLL load failed等报错原因及对应解决方案。资源为单个docx文档,约95KB,内容精炼、按问题分节,附有环境需求清单(Visual Studio 2010、GEOS、Python 2.7)和错误附录,便于按图索骥排查环境问题。已有628人学习该文档,适合在配置GDAL 1.9.2/1.11.0并配合Python 2.7时参考,可显著缩短环境搭建与排错时间。

1. 折腾两天装 GDAL,最后输给一个环境变量

这个标题不是夸张,是真实过程。为了在 Python2.7 里用上 GDAL,我在 Win7 64 位机器上整整折腾了两天,撞上了 swig 未安装、Vcvarsall.bat 找不到、DLL load failed 三座大山。最后真正卡住我的,居然只是 GDAL 的 bin 目录没加进环境变量 Path——一行配置的事,硬是让我怀疑了一晚上人生。下面把我走过的两条路,用 core 源码自编译 swig/python,以及直接装官方 msi,完整拆开:每个报错长什么样、为什么触发、怎么解决,都写清楚。给正在 Win7 64 位 + Python2.7 上装 GDAL 的同学一份能直接照着走的作业,也给后来人省点排查时间。

2. 装 GDAL 前先想清楚:编译路线还是 msi 路线

2.1 环境清单:版本对齐是第一优先级

先亮出我的环境,没对齐版本之前的一切尝试,说玄学都算客气:

  • 操作系统:Win7 SP1 64 位
  • 编译器:VS2010,对应环境变量是 VS100COMNTOOLS
  • GDAL:core 版 1.9.2,后来也尝试过 1.11.0,安装步骤通用
  • GEOS:3.3.8,GDAL 做几何运算时的依赖库
  • Python:2.7,注意我装的是 32 位版本,安装目录在 Program Files (x86)

这里有个新手最容易忽略的隐性条件:Python 2.7 时代,很多同学在 64 位系统上装的却是 32 位 Python,因为当时大量第三方扩展库只提供 32 位编译版本。GDAL 的 msi 安装包和源码编译产物都有位数之分,Python、GDAL、编译器三者的位数必须对齐,否则 import 阶段会看到各种莫名其妙的 DLL 报错,而且报错信息完全不会提示位数问题,非常坑。

版本方面多说一句。我最初直接上 GDAL 1.11.0,报错后能搜到的排查资料少,换回 1.9.2 后网上的解决办法明显变多,毕竟老版本用户基数大、踩坑记录全。Windows 平台装 GDAL,我的体会是别追新,优先用资料多的版本。1.9.2 和 1.11.0 的安装流程几乎一致,核心 DLL 文件名不同而已,前者是 gdal192.dll,后者是 gdal111.dll,环境变量配置思路完全相同。

2.2 两条路线怎么选:一张表说清楚

两条路我都实际跑过,先给结论表,再展开讲:

路线上手难度出错概率适合的人主要收获
core 源码 + swig 自编译高高想摸清 GDAL 内部结构的人能看懂调用链与 DLL 依赖关系
官方 msi 一键安装低低只打算用 GDAL 干活的人省时间,但出问题难定位

给个决策建议:如果只是要在 Python 里读栅格、做投影转换、跑栅格计算,直接走 msi 路线,别为了显得专业去编译源码。我当时想着 VS2010 反正已经装了,不如把 core 代码也研究一下,顺手查看了 apps 目录下的 gdalinfo.cpp,大致搞明白了 GDAL 读取数据的流程:先构造 GDALDataset,再按波段调用 RasterIO 读写像素,最后 Close 释放。这个理解对后面调试 import 报错有帮助,因为你至少知道 Python 端的 gdal.Open 最终会走到 C++ 的 GDALOpen,中间靠 swig 生成的包装代码和 _gdal 扩展模块搭桥。

代价同样真实:编译路线整整多花了一天半的排错时间,而且每一步报错都和环境强相关,换一台机器可能报错长得不一样。时间紧、目标明确的同学,msi 路线二十分钟内搞定。两条都试完,我更推荐的顺序是:先用 msi 把环境跑通,再回头研究源码,顺序反了很容易劝退。

2.3 理解 bin 目录和 Path:两条路线共同的终点

其实两条路线最后都会撞上同一个问题:Python 找不到 gdal192.dll。这个核心动态库,无论编译还是 msi 安装,都会落在 GDAL 的 bin 目录下。Windows 下 Python 加载 _gdal.pyd 扩展时,会按当前目录、系统目录、Path 环境变量这个顺序去搜索依赖的 DLL,而 gdal192.dll 不在其中任何一层,于是报 DLL load failed。

所以我把这条放在最前面讲:装完 GDAL 的第一件事,就是把 bin 目录加进系统环境变量 Path,而不是等报错了再去补。这个动作在两条路线里都是必须的,不做的话,无论你怎么编译、怎么安装,import gdal 这一关永远过不去。后面两章分别把两条路线的操作还原出来,每一步的报错都按我实际遇到的顺序写。

2.4 安装顺序:GEOS 必须排在 GDAL 前面

依赖顺序上,VS2010 和 GEOS 3.3.8 要在 GDAL 之前装好。GEOS 是 GDAL 做空间运算要链接的库,如果后装,编译时可能链不上,运行期也可能因为缺 geos_c.dll 而崩溃。这里有个比 DLL load failed 更隐蔽的现象:GEOS 没进 Path 时,import 可能正常,但一调用空间分析函数就崩,报错点跟安装无关,很难往环境变量上想。所以我在检查 Path 时,习惯把 GDAL 和 GEOS 两个 bin 目录一起加进去,宁可多配一条,不留暗病。

3. 编译路线实战:从 core 源码到 Python 绑定的完整步骤

3.1 第一步:用 VS2010 的 X64 命令提示符进入 swig 目录

编译 GDAL 的 Python 绑定必须在 VS 的命令行工具里做,普通 cmd 不行,因为它没有预置编译器相关环境变量。我当时用的入口是:开始菜单里找到 VS2010 的 Visual Studio 工具,选 X64 兼容工具命令提示符,右键管理员身份运行。选 X64 而不是 X86,跟位数要求直接相关,选错的话 nmake 阶段可能没事,setup.py 阶段会冒出别的链接错。

cd C:\OGC\GDAL192\gdal-1.9.2\swig nmake /f makefile.vc python

拆开解释这条命令:nmake 是 VS 自带的 make 工具,/f makefile.vc指定使用 swig 目录下这个 makefile,最后的python是目标名,让 makefile 执行生成 Python 绑定文件的相关规则。这一步会先写 setup.ini,再调用 swig 把 gdalconst.i、gdal.i 这些接口定义文件转成 C 包装代码,输出到 extensions 目录和 osgeo 目录下。

3.2 第一个坑:swig.exe 找不到

第一次跑这条命令,终端直接终止,报错内容如下:

'swig.exe' 不是内部或外部命令,也不是可运行的程序或批处理文件。 NMAKE : fatal error U1077: “swig.exe”: 返回代码“0x1”

原因很直接:GDAL 的 swig 目录里只有接口描述文件,真正把 C/C++ 接口转成 Python 绑定代码的 swig.exe 是独立工具,机器上没装。解决方法是下载 swig 2.10.0,解压到固定目录,把 swig.exe 所在目录加进系统环境变量 Path。

这里有两个注意点:第一,改完 Path 必须重新打开命令提示符,环境变量只在进程启动时读一次,旧窗口不会自动刷新;第二,建议加系统环境变量而不是用户环境变量,虽然用户变量也够用,但系统变量能让所有进程统一继承,排查时少一层变量覆盖的干扰。我第一次就是没重开窗口,又多跑了一轮。

3.3 第二步:setup.py 与 Vcvarsall.bat 的经典骗局

nmake 跑通后,继续编译安装 Python 绑定:

cd python Python setup.py build Python setup.py install

这一步会撞上第二个经典报错:

unable to find Vcvarsall.bat

网上流传的 mingw 方案我也翻过车,不是库环境对不上就是链接参数冲突。最后用的是取巧办法,在同一个命令行窗口先执行:

set VS90COMNTOOLS=%VS100COMNTOOLS%

原理是这样的:Python 2.7 的 setup.py 找编译器时,按 VS2008 的规则去查,对应环境变量是 VS90COMNTOOLS;而机器上只有 VS2010,对应的是 VS100COMNTOOLS。这一行命令把 VS2010 的工具路径复制到旧变量名上,让 setup.py 在预期位置找到 Vcvarsall.bat。执行完重新 build 和 install,会刷出一堆输出,里面有警告也有非致命错误,不用管它。判断成功的标准只有一个:检查 site-packages 下是否生成了 gdal.py、osgeo 目录和 _gdal 相关的 pyd 文件,文件在,这一步就算过了。

提示:set 命令只对当前窗口生效。中途关了窗口必须重新执行一遍,否则 setup.py 又会报找不到 Vcvarsall.bat。

3.4 第三步 import gdal:DLL load failed 的真相

编译安装都完成后,在命令行敲:

python -c "import gdal"

结果:

ImportError: DLL load failed: 找不到指定的模块。

报错堆栈指向 osgeo 目录的init.py,位置在 swig_import_helper 里加载 _gdal 扩展时。这是整个安装过程里最磨人的一个错,它不在编译阶段出现,也不在安装阶段出现,只在运行时要炸一下,而且信息极短,根本不告诉你是缺哪个模块,像一只黑匣子。网上很多方案都指向各种重装,我弯路走了不少,最后发现就是 GDAL 的 bin 目录没进 Path,Python 加载 _gdal 扩展时需要 gdal192.dll,而这个 DLL 不在搜索路径里。

解决就一步:把 GDAL 安装目录下的 bin 目录加进 Path,重开命令行再 import。注意核对路径层级,bin 目录里要能直接看到 gdal192.dll 这个文件。如果用的是 GDAL 1.11.0,文件名换成 gdal111.dll,配置思路一样,但确认文件名要按实际版本。

3.5 编译路线的额外收获:看懂调用链

回头看不亏的部分,是查看 apps 目录下的 gdalinfo.cpp 时理清了读取流程:gdalinfo 的主函数先调用 GDALOpen 构造数据集,判断文件能否打开,再遍历栅格波段,读取尺寸、投影和地理信息。这个 C++ 流程和 Python 端的 gdal.Open 完全对应,Python 只是经 swig 包装后调用同一套 C++ API。理解这条调用链后,遇到 Python 能 import 但打不开文件的问题,至少知道往数据格式、驱动注册这个方向查,而不是盯着 import 那行报错发呆。

4. msi 路线:最省事,但 DLL 的坑一个都躲不掉

4.1 官方 msi 的选择与安装

第二条路线简单很多:去官网下载对应版本的 msi 安装包,按 Python 的位数选择位数,双击一路下一步。下载页面会列出多个文件,命名里通常带版本号和位数信息,对应 Python2.7 的那个版本,文件名里一般也能看出来。Python 是 32 位就装 32 位 msi,Python 是 64 位就找 64 位 msi,交叉安装的结果就是 import 时直接 DLL load failed,报错和位数问题长得一模一样,迷惑性极强。

msi 默认装到类似 C:\Program Files\GDAL192 的目录,里面有 bin、lib、include 和 Python 绑定文件。bin 目录放的是 gdal192.dll 这类核心动态库,Python 绑定文件会装到 Python27 的 site-packages 下。路径带空格这件事值得注意:在环境变量里加路径时没问题,但如果用 setx 写 Path 拼接命令,空格可能截断字符串,导致路径没写全,回头怎么找都找不到原因。装的时候如果自定义了安装路径,一定先记下来,后面加环境变量要用。

4.2 装完照样报 DLL 错:同一个坑的两种解法

重点来了:msi 装完,直接 import gdal,照样报:

ImportError: DLL load failed: 找不到指定的模块。

跟编译路线最后一步的报错一模一样。这说明这个坑与安装方式无关,是 Windows 运行时 DLL 搜索机制的固有行为,两条路线都躲不掉。解决方案也算统一,把 bin 目录加进 Path。先给一个临时验证的思路,不动系统设置,在当前窗口跑:

# 临时追加 bin 目录,只对当前窗口生效 set Path=%Path%;C:\Program Files\GDAL192\bin python -c "import gdal"

如果这样能过,说明判断正确,再去持久化。持久化有两种写法,用 setx 的命令行方式,以及系统图形界面手动追加:

setx Path "%Path%;C:\Program Files\GDAL192\bin"

setx 会写入注册表,持久生效,但它读取的是当前会话的 Path 值再整体写回,如果当前会话的 Path 不是最新状态,存在覆盖丢失其他条目的风险。更稳妥的是走图形界面:右键我的电脑 → 属性 → 高级系统设置 → 环境变量 → 编辑 Path → 新建一行填 bin 路径。改完老规矩,所有命令行窗口和 IDE 全部重开。

还有一类情况要区分:msi 装完 import 报的不是 DLL 错,而是提示找不到 gdal 模块,那要检查 msi 的 Python 绑定选项是否安装到位,以及 Python 位数和 msi 位数是否一致。这类错在编译路线里很少见,因为编译安装会把文件直接放到 site-packages,msi 则依赖安装选项,容易被忽略。另外,如果换了 Python 位数,bin 目录里对应位数的 DLL 也要重新匹配,混用基本都会在 import 阶段露馅。

4.3 两条路线殊途同归的结论

把两条路线跑完,结论很清楚:编译路线的难点在前半程,集中在工具链和环境变量;msi 路线的难点只有后半程,就是 DLL 搜索。而 bin 目录加 Path 这一步,是两条路线共同的必经环节。如果只是要用 GDAL 干活,直接 msi 加 Path 就完事;如果想理解 GDAL 的结构和依赖关系,再回头走编译路线,这时候你会知道每一步在干什么,而不是机械复制命令。

5. 避坑清单:五条让我耗掉一整天的排错记录

5.1 swig.exe 不是内部或外部命令

现象:nmake 执行到 swig 处直接终止,提示找不到命令,附带 NMAKE fatal error U1077。

原因:swig 独立工具没装,或者装了但目录没加进 Path,make 工具在进程环境里找不到这个可执行文件。

解决:下载 swig 2.10.0,解压到固定目录,把 swig.exe 所在目录加入 Path。加完之后强制重开命令提示符,别偷懒。也不建议把 swig.exe 直接复制进系统目录,污染系统不说,以后升级版本容易冲突,而且排查时还会干扰你对真实 Path 的判断。

5.2 unable to find Vcvarsall.bat

现象:Python setup.py build 时找不到编译器配置脚本,安装直接中断。

原因:Python 2.7 的 setup.py 默认按 VS2008 查找编译环境,机器上装的是 VS2010,环境变量名对不上,导致 Vcvarsall.bat 的定位逻辑失效。

解决:执行set VS90COMNTOOLS=%VS100COMNTOOLS%后再 build。注意 set 只在当前窗口有效,换窗口要重新执行。如果以后换了大版本 Python,这类变量名兼容问题会以别的形式出现,排查思路一样:看看 setup.py 到底在查哪个变量,顺着变量名去补环境变量。

5.3 DLL load failed: 找不到指定的模块

现象:import gdal 报 DLL 加载失败,堆栈指向 osgeo 目录的init.py,位置在 swig_import_helper 加载 _gdal 时。

原因:Python 加载 _gdal 扩展时,依赖的 gdal192.dll 不在 DLL 搜索路径里,扩展模块加载失败,但报错不告诉你缺的具体文件名。

解决:把 GDAL 的 bin 目录加进 Path,重开命令行。排查时先确认 bin 路径真实存在,再确认 gdal192.dll 确实在里面,别凭记忆写路径。GDAL 1.11.0 对应的是 gdal111.dll,文件名不一样。如果加完还报,检查是不是 32/64 位混用,用 platform.architecture() 确认 Python 位数,再去核对 DLL 位数。

5.4 改了环境变量不生效

现象:Path 明明加过了,重开窗口还是报原来的错。

原因:环境变量改动只对之后新建的进程生效,旧窗口、旧 IDE、旧进程全部继承旧值,你看到的还是改动前的环境。

解决:把所有命令行窗口、Python IDE 全部关掉再重开。在 IDE 里跑代码的人最容易踩这个坑,IDE 启动于改环境变量之前,哪怕你在 IDE 里打开新终端,继承的仍是 IDE 进程的环境,必须整体退出 IDE 再启动。

5.5 安装过程一堆提示以为失败了

现象:setup.py build 和 install 刷屏,里面夹杂警告甚至非致命错误,误以为失败,反复重装。

原因:GDAL 绑定的编译过程输出大量诊断信息,多数不影响最终产物,属于正常噪音。

解决:以结果为准。检查 site-packages 下是否有 gdal.py、osgeo 目录和 _gdal 扩展文件。文件在,就继续下一步测试,不用管中间输出。我最初被这些提示吓住,反复重装了好几遍,纯属自己吓自己,浪费了整晚时间。

6. 最后验证:三行命令确认 GDAL 真能用

安装完成不等于能用,我的标准动作是写一个验证脚本跑三件事:

# -*- coding: utf-8 -*- import gdal # 导入 GDAL Python 绑定,确认模块可加载 print(gdal.VersionInfo()) # 打印版本号,确认核心库版本对得上 from osgeo import gdal # 换一种导入路径,确认包结构完整 ds = gdal.Open('d:/tmp/test.tif') # 打开真实栅格文件,触发驱动注册 print(ds.RasterXSize, ds.RasterYSize) # 输出行列数,验证读取链路通 from osgeo.gdalconst import GA_ReadOnly # 确认常量模块正常,后续读写要用

第一段确认模块能加载、版本对得上;第二段打开一个真实栅格文件,真正走一遍 GDALOpen 到数据集构造的流程;第三段确认常量模块正常。三条全过,才算真正装完。很多时候 import 能过,但 Open 一读就崩,那多半是依赖链还有缺口,比如 GEOS 的 DLL 没在 Path 里,这类问题依然从 bin 目录排查起,不要动 Python 或者重装。

复盘这次安装,最大的教训是:GDAL 在 Windows 上装好和能用是两件事,编译成功不意味着运行时没问题,msi 安装成功同样不意味着运行时没问题。从那以后,我每次装完 GDAL 都强制自己走一遍环境变量检查加这套验证脚本,两分钟的事,换掉的是几小时的血压。希望这篇记录能帮你在 Win7 64 位 + Python2.7 的组合上少走弯路,一次装通。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进