基于QGIS 3.44开发Python插件完整教程

基于QGIS 3.44开发Python插件完整教程

本教程以 QGIS LTR 3.44 为例,涵盖从零搭建插件开发环境、调试配置、自动重载以及常见 API 变更,适合已有 Python 基础的读者。


1. 环境准备

1.1 安装 QGIS 3.44

从 QGIS 官网 下载 QGIS LTR 3.44 版本。安装时确保包含 Python 环境和开发工具(OSGeo4W Shell)。

安装完成后,确认 QGIS 自带的 Python 路径,例如:

复制代码
C:\Program Files\QGIS 3.44.14\apps\Python312

1.2 使用 OSGeo4W Shell

OSGeo4W Shell 是 QGIS 自带的命令行环境,已配置好 Python 路径。在 Windows 开始菜单中搜索 OSGeo4W Shell 打开即可。

1.3 安装调试依赖 debugpy

在 OSGeo4W Shell 中执行:

bash 复制代码
pip install debugpy

也可以在 QGIS 的 Python 目录中通过命令提示符安装:

bash 复制代码
cd "C:\Program Files\QGIS 3.44.14\apps\Python312"
python -m pip install debugpy

1.4 安装相关插件

  1. Plugin Builder: 是一个帮你自动生成插件项目骨架的工具,不用从零手写一堆文件,填几个基本信息就能得到一套可直接运行的模板代码。‌‌
  2. Plugin Reloader: 允许在不重启 QGIS 的情况下重新加载插件代码,将调试效率提升数倍
  3. QGIS DevTools: 是 NextGIS 开发的插件,专为 QGIS 插件开发者设计,支持通过 debugpy 从 VS Code 远程调试插件。

以上三个插件在 QGIS 插件管理器中搜索并安装,安装完成后如图:

  • Plugin Builder按钮及弹出截图
  • Plugin Reloader按钮及弹出截图
  • QGIS DevTools按钮及弹出截图

2. 创建第一个插件

2.1 使用 Plugin Builder

  1. 在 QGIS 中安装 Plugin Builder 插件(插件管理器搜索 Plugin Builder)。
  2. 打开 插件 → Plugin Builder → Plugin Builder ,填写信息:
    • Class name :CamelCase 类名,如 MyPlugin
    • Module name :snake_case 文件名,如 my_plugin
    • Plugin name:显示在 QGIS 菜单中的名称
    • Description:一句话描述
    • Minimum QGIS version :最低兼容版本,如 3.44
  3. 选择模板(如 Tool button with dialog),生成插件骨架。

2.2 插件目录结构

生成的插件位于 QGIS 插件目录:

复制代码
C:\Users\<用户名>\AppData\Roaming\QGIS\QGIS3\profiles\default\python\plugins\myfirst

典型结构:

复制代码
myfirst/
├── __init__.py
├── myfirst.py            # 主逻辑
├── myfirst_dialog.py     # 对话框逻辑
├── myfirst_dialog_base.ui # Qt Designer 界面文件
├── icon.png
├── metadata.txt
└── ...

4. 调试方法

4.1 VS Code 断点调试配置(基于 QGIS DevTools)

步骤 1:QGIS DevTools安装完成
  • 安装后,QGIS 右下角会出现一个 bug 图标。
步骤 2:启动调试服务器
  • 点击 bug 图标,选择 Start Debugpy Server。
  • 默认监听 127.0.0.1:5678,记下端口号。DevTools 支持自定义端口范围,并可配置为 QGIS 启动时自动开启调试服务器。
步骤 3:配置 VS Code launch.json

在插件项目根目录创建 .vscode/launch.json:

json 复制代码
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Attach QGIS",
            "type": "debugpy",
            "request": "attach",
            "connect": {
                "host": "localhost",
                "port": 5678
            },
            "pathMappings": [
                {
                    "localRoot": "${workspaceFolder}",
                    "remoteRoot": "${env:APPDATA}/QGIS/QGIS3/profiles/default/python/plugins/myfirst"
                }
            ],
            "justMyCode": true
        }
    ]
}

字段说明:

  • type:使用 debugpy(旧版教程中的 python 或 ptvsd 已不推荐)。
  • request:attach 表示附加到现有进程。
  • port:必须与 DevTools 中的端口一致。
  • pathMappings:将本地 VS Code 路径映射到 QGIS 实际插件路径。remoteRoot 需指向插件在 QGIS 中的安装位置。
  • justMyCode:设为 true 可跳过 QGIS 核心代码,只在你自己的插件代码中暂停。
步骤 4:开始调试
  1. VS Code 中按 Ctrl+Shift+D 打开 Run and Debug 面板。
  2. 选择 Attach QGIS ,点击绿色启动按钮(或 F5)。
  3. 断点变为实心红点表示连接成功。
  4. 在 QGIS 中运行插件,代码会在断点处暂停,可查看变量、单步执行。

4.2 日志输出:QgsMessageLog

print() 在 QGIS 中通常不可见,推荐使用 QgsMessageLog,消息显示在 视图 → 面板 → 日志消息 中。

正确用法:

python 复制代码
from qgis.core import QgsMessageLog, Qgis

QgsMessageLog.logMessage("普通信息", "myfirst", level=Qgis.Info)
QgsMessageLog.logMessage("警告信息", "myfirst", level=Qgis.Warning)
QgsMessageLog.logMessage("严重错误", "myfirst", level=Qgis.Critical)

注意 :日志级别定义在 Qgis 类中,而非 QgsMessageLog。常见错误:QgsMessageLog.WARNING 会报 AttributeError。

5. 完整示例:获取图层并填充下拉框

5.1 UI编辑

打开Qt Designer with QGIS 3.44.14 custom widgets如图:

点击"打开"按钮,选中插件目录下的"myfirst_dialog_base.ui"文件,打开如图:

5.2 数据填充

以下代码演示从 QgsProject 获取矢量/栅格图层,并填充对话框中的下拉框:

python 复制代码
from qgis.core import QgsProject, QgsMapLayer, QgsMessageLog, Qgis

def populate_combos(dlg):
    layers = QgsProject.instance().mapLayers()
    vectors = []
    rasters = []

    for layer_id, layer in layers.items():
        if layer.type() == QgsMapLayer.VectorLayer:
            vectors.append(layer.name())
        elif layer.type() == QgsMapLayer.RasterLayer:
            rasters.append(layer.name())
        else:
            QgsMessageLog.logMessage(
                f"id: {layer_id} 的图层 [{layer.name()}] 不是栅格或矢量",
                "myfirst",
                level=Qgis.Warning
            )

    if hasattr(dlg, 'rastersCombo'):
        dlg.rastersCombo.clear()
        dlg.rastersCombo.insertItems(0, rasters)
    if hasattr(dlg, 'vectorsCombo'):
        dlg.vectorsCombo.clear()
        dlg.vectorsCombo.insertItems(0, vectors)

在 run() 方法中调用:

python 复制代码
def run(self):
    if self.first_start:
        self.first_start = False
        self.dlg = myfirstDialog()
    populate_combos(self.dlg)
    self.dlg.show()
    result = self.dlg.exec_()
    if result:
        selected = self.dlg.rastersCombo.currentText()
        QgsMessageLog.logMessage(f"用户选择: {selected}", "myfirst", Qgis.Info)

5.2 最终效果

6. 常见问题与解决

问题 原因 解决方法
ImportError: cannot import name 'QgsMapLayerRegistry' QGIS 3 已移除该类 改用 QgsProject.instance()
AttributeError: type object 'QgsMessageLog' has no attribute 'WARNING' 日志级别定义在 Qgis 类 使用 Qgis.Warning,并导入 Qgis
断点空心(未绑定) pathMappings 配置错误 检查 remoteRoot 是否与 QGIS 插件实际路径一致
连接被拒绝 调试服务器未启动或端口不一致 确认 QGIS DevTools 已启动,端口与 launch.json 一致
修改代码不生效 QGIS 加载的是已安装的插件副本 使用 Plugin Reloader 或重启 QGIS
print() 无输出 QGIS 默认不显示控制台 使用 QgsMessageLog 或从命令行启动 QGIS

7. 实用技巧与建议

  • 始终使用 QgsMessageLog 代替 print(),便于在 QGIS 内查看日志。
  • 利用 if self.first_start: 确保对话框只创建一次,避免重复初始化。
  • 使用 f-string 格式化日志信息,更简洁。
  • 在插件中合理使用 try...except,捕获异常并记录完整 traceback。
  • 推荐工作流 :使用 Plugin Reloader + Ctrl+F5 进行快速重载,配合 QGIS DevTools + VS Code 进行断点调试,形成高效的开发闭环。

相关推荐
M--Y5 小时前
LangGraph 工作流模式
开发语言·javascript·python·langchain·大模型·llm·langgraph
岁月宁静5 小时前
DeepSeek Harness 实战与架构解析:让 Agent 从“会聊”到“能交付”
人工智能·python·agent
LiaoWL1235 小时前
NumPy 入门实战(二):向量化与余弦相似度——从 ndarray 到 Embedding
python·numpy·embedding
forest_096 小时前
多 Agent 协作第二课:交叉验证≠独立验证
人工智能·python·算法·机器学习·prompt·agi
databook9 小时前
时间序列数据,先拆规律还是先查异常
python·数据挖掘·数据分析
师夷长技以自愈10 小时前
手搓 AI Agent 第 8 篇:从手写循环到画流程图——LangGraph 封装
人工智能·python
aifannihao11 小时前
Rust 1.100 的 DropGuard:用 Python 实测失败回滚与吞异常
python·rust·异常处理·标准库·contextlib
用户0190275816112 小时前
天勤 tqsdk 能做 A 股行情吗?期货强项与股票数据选型
python
2601_9679791214 小时前
pip在Python中的9个必须知道的用法
python·pip·版本控制·包管理工具·requirements.txt
曲径海盗14 小时前
【Python 学习第 58 天】列表方法
python·学习笔记·编程入门