尧图精选

QGIS 3.6.1二次开发实战:PyQGIS环境搭建、瓦片接入与批量脚本

🕒 发布时间:2026/9/1 11:32:03 📁 来源:尧图网络
简介这是一份面向QGIS 3.6.1开发者的免编译调试开发包专供Windows 10环境下使用Visual Studio 2015进行C插件开发或系统集成的读者使用。包内提供预编译的调试库文件DLL/LIB、C头文件、示例代码、API文档及CMake构建脚本并附有PDB调试符号可在VS2015中直接进行源码级断点调试彻底省去自行编译整个QGIS的繁琐流程。压缩包大小约69.99MB文件类型以库文件、头文件、示例工程和文档为主目录结构清晰便于快速引入现有项目。QGIS本身支持矢量、栅格、地形等多种地理数据格式开发者可借助这些API实现地图渲染、几何操作、空间分析等定制化任务而调试版依赖库能让开发者深入追踪核心代码执行路径快速定位错误来源。目前已有699人学习下载适合具备C基础并希望基于QGIS构建自定义功能或插件的中高级开发者。 我是做了快十年GIS开发的人这几年在生产环境里一直维系着一套基于QGIS 3.6.1的二次开发包。很多人一听“二次开发”就觉得要C、要编译SDK、要啃一堆源码其实QGIS这条路没有想象中那么陡安装版里已经内置了PyQGIS也就是官方提供的Python绑定库配合自带解释器和Processing算法框架日常的图层管理、瓦片叠加、栅格重分类、批量导出shp都能用脚本一条龙完成。这篇内容就以3.6.1为基准一次讲清环境搭建、开发路线以及高德、腾讯、百度瓦片接入和重分类这类高频操作适合正在做GIS项目、想把手工操作转成自动化流程的人参考。1. 先说清楚QGIS 3.6.1二次开发包到底是什么1.1 版本定位3.6.1在QGIS发布周期中的位置QGIS的发布节奏是每四个月左右出一个功能版本每隔几个版本才会出一个LTRLong Term Release长期支持版本。3.4是LTR3.10也是LTR而3.6.1正好卡在中间属于常规版本序列里的一个维护版本。它的内置环境是Python 3.7和Qt 5.11API已经相当成熟又比3.4那种老LTR多了一些新能力所以很多做二次开发的人愿意把这一档作为基准线。如果你去翻历史版本记录会发现3.6.1发布之后社区很快就迭代到3.8但实际项目中我并不建议一味追新。插件兼容性是个很现实的问题特别是一些第三方处理算法插件在3.8和3.10上经常要等作者适配。而3.6.1这个版本主流插件基本都跟进过了踩坑的代价最小。对于一个要长期维护的工具链来说稳定压倒一切这几乎是我选型时最重要的依据。1.2 二次开发的两条路线PyQGIS与C插件所谓“开发包”并不是一个单独的SDK安装包而是QGIS安装目录里完整的一套可调用库。它主要由三块构成一是Python绑定库存在于apps/qgis/python目录下里面是qgis.core、qgis.gui、qgis.analysis这些模块二是C动态链接库在lib目录下比如qgis_core.dll和qgis_gui.dll三是Processing算法框架它把几百个空间分析算法统一封装成可调用的处理接口。绝大多数二次开发场景走Python路线就够了也就是PyQGIS。它可以直接操作图层、地图画布、符号系统和输出报表做批量处理脚本非常顺手。C路线主要用于性能敏感的场景比如要在QGIS内部做自定义的渲染器或复杂空间索引插件那就得用CMake去引用C库从源码编译整个依赖链工程量大了不是一星半点。我见过不少团队一开始就想上C结果光编依赖就耗了两周其实需求用PyQGIS半天就完成了所以先评估清楚再选路线。2. 环境搭建把PyQGIS跑起来2.1 安装方式与目录结构开发包藏在哪里Windows环境下QGIS安装有独立安装包和OSGeo4W网络安装两种方式。做开发我强烈建议用OSGeo4W方式安装因为它会把Python解释器、Shell环境、头文件和库文件一起整理清楚后续写脚本、做插件都不用来回配路径。独立安装包更像一个“纯软件”开发依赖虽然有但不太方便调试。装好后核心目录大概是这样的C:\Program Files\QGIS 3.6.1\apps\qgis\pythonPyQGIS源码与模块C:\Program Files\QGIS 3.6.1\binQGIS主程序、Python解释器入口C:\Program Files\QGIS 3.6.1\apps\qgis\plugins插件安装目录。如果你用OSGeo4W安装路径会变成C:\OSGeo4W64\apps\qgis\python之类。开发时记住这几个路径就够了因为大部分环境问题就是Python找不到这几个目录导致的。另外要提醒一句3.6.x这个老版本在官网主页已经不在默认下载列表里需要去下载归档区域找历史版本或者从已经备份好的安装包直接装下载完成后注意核对安装程序的哈希值避免拿到被改过的文件。2.2 验证PyQGIS能否正常导入安装完成后第一步是先验证PyQGIS能不能被Python正常导入。打开OSGeo4W Shell进入Python交互环境执行下面的代码import sys sys.path.append(rC:\Program Files\QGIS 3.6.1\apps\qgis\python) from qgis.core import QgsApplication QgsApplication.setPrefixPath(rC:\Program Files\QGIS 3.6.1, True) QgsApplication.initQgis() print(PyQGIS ok)这里的setPrefixPath是告诉QGIS去哪儿找插件、图标、CRS定义等资源路径写错的话后面很多功能会莫名报错。initQgis()用来初始化QGis应用环境相当于启动一个没有界面的QGIS内核。如果这段代码能跑通开发环境就算搭好了。值得一提的是在OSGeo4W Shell里运行Python脚本时Shell会预先设置好PYTHONPATH和PATH所以脚本里可以不写sys.path.append但独立执行脚本时最好还是加上避免环境变量丢失的坑。2.3 脚本、控制台、插件三种开发形态怎么选PyQGIS开发有三种常见形态它们的适用场景完全不同。第一种是QGIS内置的Python控制台适合做快速实验和调试。在菜单栏的“插件”里打开控制台直接写代码操作当前打开的图层所见即所得。第二种是独立脚本也就是在OSGeo4W Shell里执行python my_script.py适合批量数据处理、定时任务不依赖QGIS图形界面。第三种是真正的插件开发用Plugin Builder生成插件骨架后把功能打包成带界面的工具适合交付给不会写脚本的同事用。我的经验是自己做实验用控制台项目里的一次性数据处理用独立脚本要长期交付给团队用的功能再做成插件。千万别一上来就做插件因为插件涉及加载机制、资源文件、菜单注册很多东西迭代效率远不如脚本快。3. 高频功能实操瓦片、重分类、shp导出3.1 矢量数据加载与shp导出矢量数据是GIS里最常见的点、线、面数据shpShapefile又是最通用的交换格式之一。很多新手问“qgis导出shp文件最简单方法”其实界面上两步就能完成右键图层选“导出”再选“要素另存为”格式选ESRI Shapefile即可。但在二次开发里我更推荐用代码做这件事from qgis.core import QgsVectorLayer, QgsProject, QgsVectorFileWriter layer QgsVectorLayer(rD:\data\landuse.shp, landuse, ogr) if not layer.isValid(): print(图层加载失败) else: QgsProject.instance().addMapLayer(layer) out_path rD:\out\result.shp QgsVectorFileWriter.writeAsVectorFormat( layer, out_path, UTF-8, layer.crs(), ESRI Shapefile )这里有两个细节值得注意。第一是编码参数属性表里有中文的话最好用UTF-8但如果下游是ArcGIS之类的老软件可能需要选GBK否则打开会出现乱码。第二是shp格式本身限制字段名不能超过10个字符中文字段名尤其容易出问题导出前先改成英文短字段名能省很多麻烦。另外writeAsVectorFormat默认导出全部要素如果只想把选中要素导出去需要额外传入要素请求或先复制选择集。说到矢量数据顺便纠正个常见错别字很多人会把“矢量图”写成“适量图”其实是同一回事只是输入法惹的祸。矢量数据用坐标点、线和面记录空间对象和栅格数据那种像元矩阵完全不是一个逻辑所以处理方式也不同。3.2 自定义XYZ瓦片接入高德、腾讯与百度QGIS 3.6之后XYZ瓦片底图的接入变得非常轻松。界面操作路径是图层 - 添加图层 - 添加XYZ图层 - 新建然后把瓦片URL模板填进去。常用的模板我整理了一张表来源URL模板坐标系高德矢量https://webrd0{s}.is.autonavi.com/appmaptile?langzh_cnsize1scale1style8x{x}y{y}z{z}GCJ-02高德影像https://webst0{s}.is.autonavi.com/appmaptile?style6x{x}y{y}z{z}GCJ-02腾讯地图https://rt{0-3}.map.gtimg.com/tile?z{z}x{x}y{y}styleid1GCJ-02百度地图https://maponline0{s}.bdimg.com/tile/?qtvtilex{x}y{y}z{z}stylesplscaler2BD09在PyQGIS脚本里加载瓦片的方式也很直接from qgis.core import QgsRasterLayer, QgsProject url typexyzurl https://webrd0{s}.is.autonavi.com/appmaptile?langzh_cnsize1scale1style8x{x}y{y}z{z} rl QgsRasterLayer(url, 高德, wms) if rl.isValid(): QgsProject.instance().addMapLayer(rl)这里有一个特别重要的点高德和腾讯用的是GCJ-02坐标系百度用的是BD09它们和GPS常用的WGS84之间存在偏移。如果你把瓦片加载进来后发现和矢量数据对不上八成不是瓦片坏了而是坐标系没对齐。做精确分析时要么把矢量和栅格统一到同一个坐标系要么用控制点做配准。另外在线瓦片服务适用于学习和项目验证正式上线前要确认数据授权范围局域网离线部署时可以考虑用瓦片下载工具导出MBTiles这也是“qgis地图下载”相关热词背后真正想解决的问题。3.3 栅格重分类两种实现路径栅格数据和矢量数据是两种完全不同的数据结构栅格的本质是像元矩阵每个像元存一个数值。重分类就是按照数值范围把像元重新赋值比如把高程数据分成低、中、高三类或者把土地利用类型编号重新映射。在QGIS 3.6.1里做重分类最直接的方法是菜单栏的“栅格” - “栅格计算器”。比如要把DEM数据按高程分成三个等级可以用这个表达式if(dem1 IS NOT NULL, (dem1 100) * 1 (dem1 100 AND dem1 200) * 2 (dem1 200) * 3, dem1)这个表达式会把小于100的区域赋值为1100到200之间赋值为2大于等于200赋值为3而且专门用if包了一层让原本的NoData区域保持NoData不会变成0。很多新手写完表达式觉得没毛病一看结果整张图都是0多半就是漏了NoData处理。另一种路径是Processing工具箱里的SAGA算法搜索“Reclassify values”就能找到。它支持直接填旧值和新值的映射表不用写函数表达式适合重分类规则复杂的场景。注意SAGA算法在中文环境下输入栅格必须同时有正确的投影和范围信息否则会报“Invalid grid”之类的错误。3.4 从界面点击到脚本批量执行界面操作适合单次处理但做项目时往往面对几十个文件这时候就得靠脚本。我在实际工作中经常做的一件事是把一个目录下所有shp统一转成UTF-8编码并加个前缀import glob from qgis.core import QgsVectorLayer, QgsVectorFileWriter for shp in glob.glob(rD:\data\*.shp): layer QgsVectorLayer(shp, tmp, ogr) if not layer.isValid(): continue out shp.replace(.shp, _out.shp) QgsVectorFileWriter.writeAsVectorFormat(layer, out, UTF-8, layer.crs(), ESRI Shapefile) print(导出:, out)如果是重分类批量任务可以在脚本里调用Processing算法。QGIS 3.6中栅格计算器的Processing算法ID是qgis:rastercalculator调用时参数值会有差异第一次跑之前建议先在Processing工具箱里手动执行一次然后查看“历史”菜单里的命令拿到精确的参数结构再写脚本。脚本化之后的效率提升非常明显原来一个下午手工点几十遍的操作现在两分钟跑完。4. 实际开发中的高频问题与排查4.1 模块导入失败找不到qgis.core这是新环境最常见的问题。脚本运行时提示ModuleNotFoundError: No module named qgis.core本质是Python没有找到PyQGIS的目录。解决方法有两个一是像前面说的在脚本开头用sys.path.append手动加入apps\qgis\python路径二是用OSGeo4W Shell启动Python它会自动把环境变量配好。我建议开发环境统一用OSGeo4W Shell部署环境再考虑独立打包这样能省掉大量环境匹配的麻烦。4.2 XYZ瓦片加载后空白或位置偏移瓦片空白通常有三个原因URL模板里的{s}通配符用不了、当前网络访问不了该瓦片域名、或者图层CRS设置不对。检查时先把URL复制到浏览器里替换成具体的数字和坐标如果浏览器能显示图片说明URL没问题再回QGIS里排查。位置偏移的问题根源基本是坐标系不一致。高德、腾讯的GCJ-02和百度的BD09与WGS84之间有系统性偏移叠加WGS84数据时需要对底图做偏移修正或者用专门的转换插件不要指望手动拖动图层能对齐。4.3 属性表中文乱码与字段丢失shp导出后中文乱码十有八九是编码参数选错了。UTF-8导出的文件给QGIS自己用没问题但给ArcGIS系列用就容易乱这时选GBK试试。更隐晦的问题是字段名被截断shp的DBF字段名最长10字节中文一个字占两三个字节很容易截断成乱字符。我处理这类问题有一个原则导出给外部系统的shp字段名全部用英文属性值里的中文尽量用代码映射表转换。4.4 重分类结果全0或NoData区异常重分类结果全为0先看原栅格是不是有大量NoData。表达式里如果直接(dem1 100) * 1NoData参与比较时会得到NULL而不是有效值有时候QGIS会把它渲染成0所以结果看起来一片黑。用if(dem1 IS NOT NULL, 表达式, dem1)包一层能保留NoData。另外重分类输出格式建议选GeoTIFF不要选ESRI Grid后者对NoData的处理在某些情况下会额外占磁盘还容易写出全0的伪值。为了让大家排查时有依据我把最常踩的坑整理成一张速查表现象原因排查思路模块导入失败PYTHONPATH未包含PyQGIS目录用OSGeo4W Shell或手动追加路径瓦片空白URL失效、网络受限、通配符错误浏览器测试URL模板瓦片偏移GCJ-02/BD09与WGS84不一致统一CRS或做坐标转换shp中文乱码编码参数不匹配UTF-8与GBK互相切换重分类全0表达式未处理NoData用is not null条件包裹5. 这套方案用下来的几点经验5.1 PyQGIS与Processing的分工实际项目里我会把工作分成两类。一类是现成算法能解决的比如坡度坡向计算、缓冲区分析、影像裁剪直接调用Processing里的算法稳定可靠另一类是自定义逻辑和批量控制流的比如遍历文件夹、判断条件、动态拼接表达式这种就用PyQGIS写循环。两者结合的好处是代码量少、出错的概率低也方便其他同事接手。5.2 维护开发环境的几条心得踩过几次坑之后我现在维护这套3.6.1环境有四个习惯第一版本锁死绝不随手升级同一套代码在不同QGIS版本上的行为差异比想象中大得多第二所有路径尽量用英文全中文路径在某些GDAL版本下会触发编码问题第三复杂操作封装成函数统一放一个工具模块里后续调用方便第四保留一套干净的OSGeo4W环境别在系统Python里乱装包否则依赖冲突会让人怀疑人生。最后再分享一个实用小技巧在写PyQGIS脚本时如果某个处理算法参数搞不清楚先手动执行一次再到“处理”菜单里的“历史”里复制Python代码。这个功能相当于把界面操作翻译成了脚本是我学习Processing算法最快的方式。QGIS 3.6.1这套二次开发包到现在依然能扛住很多生产任务希望这篇分享能帮你少走一段弯路。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联 返回资讯列表 →