1. 为什么需要批量导出geojson在日常GIS数据处理工作中我们经常遇到需要将多个矢量图层统一导出为geojson格式的情况。比如我最近接手的一个城市基础设施项目需要处理超过200个不同类别的矢量图层如果一个个手动导出不仅耗时费力还容易出错。这时候一个自动化脚本就能帮上大忙。geojson作为一种轻量级的地理数据交换格式在web地图开发、移动端应用和数据共享中有着广泛的应用。它基于JSON标准人类可读性强同时又能完整保留地理要素的几何信息和属性数据。实测下来相比shapefile等传统格式geojson在跨平台使用时更加稳定可靠。在QGIS中虽然可以通过右键菜单手动导出单个图层但当面对几十上百个图层时这种方法就显得力不从心了。我踩过的坑告诉我手动操作不仅效率低下还容易遗漏某些图层或者搞混导出路径。这就是为什么我们需要借助Python脚本来实现批量导出的自动化流程。2. 环境准备与基础配置2.1 确保QGIS Python环境正常在开始编写脚本前我们需要确认QGIS的Python环境已经配置妥当。打开QGIS后点击顶部菜单栏的插件→Python控制台这会打开一个交互式的Python命令行界面。在这里输入简单的Python命令如print(Hello QGIS)如果能够正常输出说明环境没有问题。我建议在正式编写脚本前先熟悉几个常用的QGIS Python模块qgis.core包含QGIS核心功能的接口qgis.gui提供图形界面相关的类qgis.utils包含实用工具函数2.2 创建脚本编辑器虽然可以在Python控制台直接输入代码但对于较长的脚本使用脚本编辑器会更方便。点击Python控制台工具栏上的显示编辑器按钮图标看起来像个文本文件这会打开一个功能更完善的代码编辑器窗口。这里有个小技巧我习惯把常用的脚本保存为.py文件存放在固定的目录下。这样下次使用时可以直接打开不用重新编写。编辑器支持语法高亮和基本的代码补全对于Python开发来说已经足够用了。3. 核心脚本编写详解3.1 理解脚本的基本结构让我们仔细分析这个批量导出脚本的每个部分。首先需要导入必要的模块from qgis.core import QgsProject, QgsVectorFileWriter, QgsCoordinateReferenceSystem这三个类分别负责QgsProject管理当前QGIS项目中的所有图层QgsVectorFileWriter处理矢量数据的写入操作QgsCoordinateReferenceSystem定义坐标参考系统接下来定义主函数def export_layers_to_geojson(output_folder): # 获取当前项目中的所有图层 layers QgsProject.instance().mapLayers().values() # 遍历所有图层 for layer in layers: # 检查是否为矢量图层 if layer.type() QgsMapLayer.VectorLayer: # 构造输出路径 output_file f{output_folder}/{layer.name()}.geojson # 设置导出选项 options QgsVectorFileWriter.SaveVectorOptions() options.driverName GeoJSON options.fileEncoding UTF-8 # 执行导出 QgsVectorFileWriter.writeAsVectorFormat( layer, output_file, options ) print(fExported: {layer.name()} to {output_file})3.2 关键参数解析与优化在实际使用中我发现有几个参数值得特别注意输出路径处理Windows和Linux系统的路径分隔符不同建议使用os.path.join来确保跨平台兼容性。比如import os output_file os.path.join(output_folder, f{layer.name()}.geojson)编码设置虽然UTF-8是通用编码但遇到特殊字符时可能会出现问题。可以添加错误处理try: QgsVectorFileWriter.writeAsVectorFormat(layer, output_file, options) except Exception as e: print(fFailed to export {layer.name()}: {str(e)})坐标系转换如果需要统一输出坐标系可以在options中添加options.ct QgsCoordinateTransform( layer.crs(), QgsCoordinateReferenceSystem(EPSG:4326), # WGS84 QgsProject.instance() )4. 高级功能扩展4.1 按条件筛选图层有时候我们只需要导出特定类型的图层。比如只导出多边形图层可以修改判断条件if (layer.type() QgsMapLayer.VectorLayer and layer.geometryType() QgsWkbTypes.PolygonGeometry): # 导出操作或者根据图层名称过滤if buildings in layer.name().lower(): # 导出操作4.2 批量设置属性选项geojson支持多种导出选项我们可以通过修改SaveVectorOptions来定制输出options.includeZ True # 包含Z值 options.attributes [name, type] # 只导出指定属性 options.symbologyExport QgsVectorFileWriter.SymbolLayerSymbology # 导出符号系统4.3 进度反馈与日志记录对于大量图层的导出添加进度反馈很有必要total len([l for l in layers if l.type() QgsMapLayer.VectorLayer]) current 0 for layer in layers: if layer.type() QgsMapLayer.VectorLayer: current 1 print(fProcessing {current}/{total}: {layer.name()}) # 导出操作更专业的做法是写入日志文件import logging logging.basicConfig(filenameexport.log, levellogging.INFO) # 在导出成功后添加 logging.info(fSuccessfully exported {layer.name()})5. 实际应用案例分享去年我在处理一个智慧城市项目时需要将全市的POI数据约150个图层导出为geojson供前端使用。手动导出不仅耗时还经常因为内存不足导致QGIS崩溃。改用这个脚本后整个导出过程只需要3分钟而且完全自动化。另一个案例是为移动应用准备离线地图数据。我们每周都需要更新一次数据使用这个脚本后只需简单修改输出路径就能完成全部工作节省了大量人力成本。有个小技巧我会在脚本开头添加一个时间戳这样导出的文件会自动包含日期信息方便版本管理from datetime import datetime timestamp datetime.now().strftime(%Y%m%d) output_folder fD:/exports/{timestamp}6. 常见问题排查6.1 导出失败的可能原因根据我的经验导出失败通常有以下几个原因路径权限问题确保输出文件夹有写入权限图层锁定某些图层可能被其他程序占用内存不足处理大型图层时可能需要增加QGIS内存限制特殊字符图层名称或属性中包含特殊字符可能导致问题6.2 性能优化建议当处理大量数据时可以尝试以下优化关闭不必要的QGIS插件增加Python的递归限制sys.setrecursionlimit(10000)分批处理将图层分成若干组分别导出使用多线程高级技巧需要谨慎处理QGIS的线程安全6.3 调试技巧遇到问题时可以逐步缩小范围先尝试导出单个图层检查中间变量值添加详细的错误日志在QGIS Python控制台交互测试代码片段7. 与其他工具的集成这个脚本可以很容易地集成到自动化工作流中。比如结合Windows任务计划或Linux的cron可以实现定时自动导出。我通常会在导出完成后自动调用压缩工具打包文件import zipfile with zipfile.ZipFile(output.zip, w) as zipf: for file in os.listdir(output_folder): if file.endswith(.geojson): zipf.write(os.path.join(output_folder, file))对于更复杂的场景可以考虑将脚本封装为QGIS插件或者通过PyQGIS的API与其他Python程序交互。比如导出完成后自动上传到Web服务器import requests for file in os.listdir(output_folder): if file.endswith(.geojson): with open(os.path.join(output_folder, file), rb) as f: requests.post(http://example.com/upload, files{file: f})8. 最佳实践建议经过多次项目实践我总结出以下几点经验保持代码可读性添加适当的注释和文档字符串参数化配置将输出路径等可变参数提取为脚本开头变量错误处理预料可能的问题并妥善处理版本控制将脚本纳入Git等版本管理系统代码复用将通用功能封装为函数方便其他脚本调用一个更健壮的脚本模板如下#!/usr/bin/env python QGIS矢量图层批量导出geojson脚本 作者你的名字 日期2023-08-20 import os from datetime import datetime from qgis.core import QgsProject, QgsVectorFileWriter, QgsMapLayer def export_layers(output_folder, filter_funcNone): 导出所有符合条件的矢量图层到指定文件夹 Args: output_folder: 输出目录路径 filter_func: 可选图层过滤函数 Returns: tuple: (成功数, 失败数) if not os.path.exists(output_folder): os.makedirs(output_folder) layers QgsProject.instance().mapLayers().values() success 0 fail 0 for layer in layers: if layer.type() ! QgsMapLayer.VectorLayer: continue if filter_func and not filter_func(layer): continue try: output_file os.path.join(output_folder, f{layer.name()}.geojson) options QgsVectorFileWriter.SaveVectorOptions() options.driverName GeoJSON QgsVectorFileWriter.writeAsVectorFormat(layer, output_file, options) success 1 except Exception as e: print(fError exporting {layer.name()}: {str(e)}) fail 1 return (success, fail) if __name__ __main__: # 使用示例 output_dir os.path.expanduser(~/geojson_exports) timestamp datetime.now().strftime(%Y%m%d_%H%M) final_output os.path.join(output_dir, timestamp) print(f开始导出到 {final_output}) success, fail export_layers(final_output) print(f导出完成: {success}个成功, {fail}个失败)