ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

QGIS插件开发:环境配置、调试与打包发布全流程

2026/10/1 4:47:49 拓冰建站 浏览量
QGIS插件开发:环境配置、调试与打包发布全流程 1. 先说清楚QGIS 插件开发为什么不能当成普通 Python 项目来做1.1 插件不是独立程序它是寄生在 QGIS 进程里的一段代码这是所有新手最容易走偏的地方。你写一个普通的 Python 脚本python main.py就能跑进程是你自己启动的依赖是你自己 pip 装的。QGIS 插件完全不是这个逻辑插件是一段被 QGIS 主程序在运行时动态加载的 Python 代码它运行在 QGIS 已经启动好的那个 Python 解释器进程里用的也是 QGIS 自带的 PyQt5 版本、自带的 GDAL 和 PROJ 库、自带的那套 Python site-packages。举个生活化的类比普通 Python 项目像是你自己开一家店租店面、进货、装修全由你决定QGIS 插件像是你在别人的商场里租一个柜台水电、消防、客流全是商场给的你只能按商场的规矩来。所以你在编辑器里能不能import qgis.core成功并不是看你 pip 装了多少东西而是看编辑器有没有用上 QGIS 那套 Python 和那套环境变量。理解了这一层后面所有的配置动作就有了统一的判断标准凡是能让编辑器借用 QGIS 自带 Python 环境的做法都是对的凡是试图用系统 Python 硬装 PyQGIS 的做法基本都是弯路。PyQGIS 在 pip 上没有官方可分发的独立包强行安装会遇到 SIP 绑定、Qt 版本、GDAL 编译链一堆问题投入产出比极低。所以整套环境配置的核心目标只有三个让编辑器能读到 QGIS 的 Python 解释器、让import qgis.core能成功、让改完的代码能快速在 QGIS 里看到效果。剩下的都是围绕这三件事的细节。1.2 三种环境配置路线各自适合什么样的人实际工作中我见过并试过三条路线各有取舍先把结论摆出来你对号入座。路线做法优点缺点适合谁路线 AQGIS 自带控制台直接在 QGIS 里打开 Python 控制台写代码零配置立刻能跑没有补全、没有断点、代码管理困难只做实验、验证 API路线 BOSGeo4W Shell 启动编辑器从 QGIS 附带的命令行环境里启动 VS Code / PyCharm环境变量完整继承import qgis.core一次通过每次要从 Shell 里启动绝大多数开发场景路线 C手工配置解释器与 env在编辑器里手动指定解释器、PYTHONPATH、PATH启动方式自由能做调试配置路径多、版本升级易失效想深度整合调试的人路线 B 是我最推荐的起点。原因很直接QGIS 附带的o4w_env.bat会把PATH、PYTHONPATH、GDAL_DATA、PROJ_LIB、QT_PLUGIN_PATH这些变量一次性设好你在那个环境里启动的编辑器天然就继承了全部配置省掉大量试错时间。等你对这套东西熟了再去做路线 C 的精细配置。路线 C 不是不必要而是进阶选项。它的价值在于调试只有环境变量在编辑器里被正确声明断点调试才可能跑通。而环境变量的具体内容你完全可以从路线 B 的环境里抄出来。1.3 配错了会长什么样三种典型报错先认清提前认识报错比事后瞎猜快得多。以下三种几乎每个新手都会遇到ModuleNotFoundError: No module named qgis。这说明解释器根本不知道 PyQGIS 在哪。要么解释器指错了用了系统 Python要么PYTHONPATH里没加 QGIS 的 python 目录。ImportError: DLL load failed while importing core: 找不到指定的模块。这个是 Windows 上最经典的坑说明PYTHONPATH对了但PATH里缺 QGIS 的bin目录导致 Qt 的 DLL 加载不到。加路径没用得加对顺序。插件出现在列表里但打勾后无反应或者勾完立刻掉回未勾选状态。这通常是插件本身的代码问题__init__.py里的classFactory写错了、metadata.txt字段缺失、或者运行时报了异常被 QGIS 静默吞掉。第三种最坑因为 QGIS 默认不会把插件的加载异常直接弹出来。排查手段后面第 5 章会详细讲。现在你只需要记住环境问题报错在 import代码问题报错在加载。分清这两类排查方向就不会跑偏。2. 装 QGIS 与装编辑器路径这一步决定了后面顺不顺2.1 选 LTR 还是最新版安装目录要不要改QGIS 的 Windows 安装包分两类LTR长期支持版和 Latest最新版。做插件开发请优先选LTR。理由不是保守而是插件兼容性LTR 版本的 API 更稳定你写的一次代码能覆盖的人群更广最新版可能引入了还没被广泛测试的 API 变化早期的插件会在这些版本上直接报错。安装目录这一项很多人图省事直接点默认的C:\Program Files\QGIS 3.xx.x\这本身没问题但你要接受一个后果这个路径带空格还带版本号。带空格会导致后面在命令行、脚本、配置里引用时必须加引号稍不留神就是一堆诡异错误。带版本号意味着你以后升级 QGIS 时所有配置里的路径都要跟着改。我的做法是不改默认路径但把版本号单独记下来并且所有配置里引用路径都老老实实加引号。改到C:\QGIS\这种短路径虽然看着干净但和官方文档、社区教程里的路径对不上反而增加沟通成本。安装组件这一步也要留意。自定义安装界面里有一堆可选组件做插件开发有两个别漏Python 相关的组件PyQt5、Python 解释器本体以及 Qt 的工具链。如果你用的是网络安装器OSGeo4W 那套确保勾选qgis-ltr-full这类完整包别只装了残缺的精简版否则后面pyrcc5找不到。装完之后第一件事是打开 QGIS从菜单里找到 Python 控制台一般在插件菜单下或者用工具栏那个 Python 图标。能打开、能敲一行print(ok)并且窗口里出现ok说明基础环境没问题。2.2 编辑器选型VS Code、PyCharm还是先用自带控制台编辑器这件事不用纠结太久三个选项的实际差别在于你要花多少时间在配置上。QGIS 自带的 Python 控制台是零配置的打开就能跑iface、QgsProject这些对象都是现成的。它的定位是探路工具你写插件时不确定某个 API 怎么调用先在控制台里敲两行验证验证通过再搬进代码。但别指望用它写正式项目——没有代码补全、没有版本管理、没有断点写超过两百行的插件就是自虐。VS Code 是大多数人的选择免费、轻量、插件生态好。要注意的是 Python 扩展和 Pylance 这两块是必须装的Python 扩展提供解释器管理和调试Pylance 提供补全和类型提示。装完这两个PyQGIS 的补全才能通过extraPaths生效。PyCharm 社区版也能用它对大型项目的重构和跳转更顺手但解释器和路径要在设置里手工配配置条目比 VS Code 多。PyCharm 专业版有远程调试和更强的调试器不过是付费的。我的建议先用 QGIS 自带控制台把 API 摸熟然后直接上 VS Code。别在编辑器选型上反复横跳时间和精力都应该花在写插件逻辑上。三大平台的插件目录差异也顺便记一下后面生成插件时会反复用到WindowsC:\Users\用户名\AppData\Roaming\QGIS\QGIS3\profiles\default\python\pluginsLinux~/.local/share/QGIS/QGIS3/profiles/default/python/pluginsmacOS~/Library/Application Support/QGIS/QGIS3/profiles/default/python/plugins最省事的确认方式是在 QGIS 的 Python 控制台里跑这两行from qgis.core import QgsApplication print(QgsApplication.qgisSettingsDirPath()) import qgis.utils print(qgis.utils.plugin_paths())第一行输出你的活动 profile 目录第二行输出插件搜索路径列表。不要凭记忆写路径永远以这两行的输出为准。版本不同、用户目录带中文、装了多份 QGIS这些情况都会让我记得是那个路径变成错误。2.3 profile 目录、插件目录、缓存目录别混为一谈这三个目录很容易被当成一回事实际职责完全不同。profile 目录是整个用户配置的根里面装着界面布局、最近打开的项目、坐标系设置、已启用插件的清单以及python/plugins这个子目录。你在 QGIS 里点设置 → 用户配置 → 打开活动配置文件夹打开的就是它。插件目录是 profile 目录下的python/plugins所有第三方插件包括你自己开发的都放在这儿。QGIS 启动时会扫描这个目录逐个读metadata.txt判断能不能加载。缓存目录则是python/plugins同级的cache之类的位置一些插件会把临时数据写在这里。清缓存不等于删插件这一点要分清楚。还有一个隐藏的坑QGIS 会记住哪些插件被启用过。这个状态存在 profile 目录下的一个配置文件里。你手动删了插件文件夹但没重启 QGIS插件列表里可能还残留着条目反过来你新拷进去一个插件但没重启它可能不出现。改插件文件后要么用 Plugin Reloader第 4 章讲要么老老实实重启 QGIS。顺带提一下如果你不想污染默认 profile可以在 QGIS 启动时用--profile参数指定一个新 profile这样插件、设置都是独立的。做实验性开发时很有用。3. 让编辑器真正看见 PyQGIS解释器与路径配置全流程3.1 找到 QGIS 自带的 Python 与那几个 bat 脚本这一步是整个配置的基石先把你机器上的文件找齐。打开 QGIS 的安装目录进入apps子目录里面应该能看到一个类似Python39、Python312这样的文件夹版本号取决于你装的 QGIS 版本3.28 和 3.34 常见的是 Python 3.93.40 之后常见的是 3.12以你机器上实际存在的为准别照抄。里面那个python.exe就是 QGIS 自带的解释器。注意它和系统的 Python 是两套东西互不干扰你也别尝试用它去装系统的包。再看安装目录下的bin文件夹里面有几个批处理脚本很关键python-qgis.bat和python-qgis-ltr.bat启动一个已经加载好 QGIS 环境的 Python 交互式环境o4w_env.bat只设置环境变量不启动 Pythonqgis-ltr-bin.exeQGIS 主程序本体o4w_env.bat是重中之重。在普通命令提示符里执行它当前会话就会获得 QGIS 的全部环境变量。你可以这样验证call C:\Program Files\QGIS 3.34.0\bin\o4w_env.bat python -c import qgis.core; print(qgis.core.Qgis.QGIS_VERSION)如果这一行能打印出版本号说明 QGIS 自带的环境是完整可用的问题就只剩怎么让编辑器也用上这个环境。注意o4w_env.bat只在当前命令行会话生效关掉窗口就没了。不要指望把它加到系统环境变量里一劳永逸那样会污染系统 Python 的正常使用。3.2 VS Codesettings.json、终端 profile 与解释器三件套VS Code 的配置分三层层与层之间容易互相打断按顺序来。第一层是终端 profile。在settings.json里加一段让 VS Code 的集成终端可以选择性地以 QGIS 环境启动{ terminal.integrated.profiles.windows: { QGIS Env: { path: C:\\Windows\\System32\\cmd.exe, args: [/k, \C:\\Program Files\\QGIS 3.34.0\\bin\\o4w_env.bat\] } }, terminal.integrated.defaultProfile.windows: QGIS Env }配完之后VS Code 里新开的终端会自动带上 QGIS 的环境变量。这是最省心的做法因为接下来不管你是敲python还是敲pip用的都是 QGIS 那套。第二层是解释器。按下CtrlShiftP输入Python: Select Interpreter然后手动输入路径指向C:\Program Files\QGIS 3.34.0\apps\Python39\python.exe选完之后 VS Code 状态栏会显示这个解释器。注意别选成系统里的 Anaconda 或微软商店版 Python这是新手最常见的失误。第三层是补全路径。光选解释器还不够因为 QGIS 的 Python 库不在标准 site-packages 里Pylance 找不到它。需要手工加{ python.analysis.extraPaths: [ C:\\Program Files\\QGIS 3.34.0\\apps\\qgis\\python, C:\\Program Files\\QGIS 3.34.0\\apps\\qgis\\python\\plugins ], python.autoComplete.extraPaths: [ C:\\Program Files\\QGIS 3.34.0\\apps\\qgis\\python, C:\\Program Files\\QGIS 3.34.0\\apps\\qgis\\python\\plugins ] }加完之后重启一下 VS Code或者执行Python: Restart Language Server再打开一个.py文件敲from qgis.core import QgsProject如果QgsProject有补全提示、能跳转到定义说明补全这块通了。如果还要在 VS Code 里直接运行脚本就得配launch.json了这属于路线 C 的范畴{ version: 0.2.0, configurations: [ { name: QGIS 环境跑当前文件, type: debugpy, request: launch, program: ${file}, console: integratedTerminal, env: { PYTHONPATH: C:\\Program Files\\QGIS 3.34.0\\apps\\qgis\\python;C:\\Program Files\\QGIS 3.34.0\\apps\\qgis\\python\\plugins, PATH: C:\\Program Files\\QGIS 3.34.0\\bin;C:\\Program Files\\QGIS 3.34.0\\apps\\qgis\\bin;${env:PATH} } } ] }这套 env 写法是够用版本。完整版还要加GDAL_DATA、PROJ_LIB、QT_PLUGIN_PATH具体值请从o4w_env.bat里抄或者在一个已经执行过它的终端里敲set查看。不要凭印象写这些变量路径错一个字母就是 DLL 加载失败。3.3 PyCharm解释器、路径变量与外部工具PyCharm 的配置思路和 VS Code 一致但入口分散在几个地方。解释器在File → Settings → Project → Python Interpreter。点齿轮图标选Add然后选System Interpreter路径填C:\Program Files\QGIS 3.34.0\apps\Python39\python.exe。添加完之后 PyCharm 会去扫这个解释器的 site-packagesQGIS 自带的那些库会被识别到。但 PyQGIS 不在 site-packages 里所以要再手工加路径位置在Settings → Project → Python Interpreter → 解释器右侧的路径按钮把apps\qgis\python和apps\qgis\python\plugins加进去。加完之后 PyCharm 的索引会重建一次耐心等。PyCharm 还有一个更好用的东西是外部工具配置。在Settings → Tools → External Tools里加一个工具命令指向o4w_env.bat每次点一下就能在一个带 QGIS 环境的终端里干活。对不想改launch.json的人来说这比手工配 env 靠谱。PyCharm 运行/调试配置里的环境变量编辑框直接粘贴从o4w_env.bat抄来的那几个变量即可。要注意 PyCharm 的环境变量编辑框里多条路径之间用的是分号分隔且不要用引号把整条PATH值包起来。3.4 验证环节怎样才算真的配好了配置完别急着写插件先做三层验证一层通不了就别往下走。第一层解释器认对了。在编辑器的文件里写import sys print(sys.executable) print(sys.version)运行并看输出路径必须指向 QGIS 安装目录里的python.exe而不是C:\Python3xx或者 Anaconda。第二层PyQGIS 能导入。同一个文件里加from qgis.core import QgsApplication, Qgis print(Qgis.QGIS_VERSION)能打印出版本号说明导入链路和 DLL 加载都没问题。如果这里报DLL load failed回去检查PATH里有没有bin目录并且确认bin排在系统 Python 相关路径前面。第三层补全和跳转可用。随便敲一个QgsVectorLayer(看有没有参数提示按住Ctrl点类名看能不能跳到qgis/core/__init__.pyi或者对应的源码。这两项都通过才算是一个真正好用的开发环境。提示如果第二层过了、第三层没过通常是 Pylance 的缓存问题执行一次Python: Restart Language Server就好。如果第三层过了、第二层没过那是运行时环境变量的问题不是编辑器的问题要往o4w_env.bat的方向查。4. 生成第一个插件骨架Plugin Builder 与它的产物解剖4.1 安装 Plugin Builder 并生成骨架有了环境下一步就是造一个能加载进 QGIS 的插件骨架。手写骨架不是不行但metadata.txt字段多、__init__.py的classFactory有固定写法、资源文件要编译手写容易漏东西。所以推荐用Plugin Builder这个官方社区插件生成模板再按需修改。安装路径是 QGIS 里的插件 → 管理并安装插件搜索框输入 Plugin Builder找到后点安装。装完后菜单里会多出一项。使用流程大致是点开 Plugin Builder填一组表单然后选择输出目录。表单里几项要特别注意Class name插件主类的名字建议用英文驼峰别用中文也别和 QGIS 内置类名撞车。Plugin name显示在菜单和插件管理器里的名字可以是中文但建议保留英文原名做目录名方便社区发布。Module name这个决定了文件夹名和 Python 模块名必须是纯小写英文加下划线。Description / About这两项会写进metadata.txt是发布时给别人看的门面先大致填发布前再打磨。Minimum QGIS version这个值直接决定插件能在哪些版本上被加载填太高会让老用户装不上填太低可能在不支持的版本上出问题。保守做法是填你实际测试过的最低版本比如3.22。Template选Tool button with dialog或者Tool button with dock widget前者适合弹窗式工具后者适合常驻面板。输出目录建议直接填到插件目录第 2.2 节那个路径下。Plugin Builder 会自动建子目录你确认一下生成的位置对不对。4.2 逐个文件拆解哪些要改、哪些别碰生成出来的目录大概长这样my_first_plugin/ ├── __init__.py ├── metadata.txt ├── my_first_plugin.py ├── my_first_plugin_dialog.py ├── my_first_plugin_dialog_base.ui ├── resources.qrc ├── resources.py ├── icon.png ├── Makefile └── i18n/ └── af.ts挨个说清楚每个文件干什么、能不能动。metadata.txt是插件的身份证。QGIS 启动扫描时只读这个文件来判断插件是否可用。关键字段包括name、qgisMinimumVersion、description、version、author、email、about、tracker、repository、tags、experimental。version字段每次发布必须递增否则插件仓库会拒绝。experimentalTrue表示标记为实验版只有勾选了显示实验性插件的用户才能看到。这个字段在你自测阶段可以开着正式发布时改成False。__init__.py是插件入口里面的classFactory函数负责把插件类交给 QGIS。这个文件很短但千万别改结构只改返回的类名def classFactory(iface): from .my_first_plugin import MyFirstPlugin return MyFirstPlugin(iface)my_first_plugin.py是核心逻辑主类里固定有这么几个方法__init__(self, iface)构造iface是 QGIS 给你的接口对象通过它能访问图层树、菜单、工具栏、状态栏。initGui(self)QGIS 加载插件时调用通常在这里把动作QAction加到菜单和工具栏。unload(self)插件被卸载时调用要在这里把你加进去的动作从界面移除不然会出现重复菜单项。run(self)动作被点击时触发业务逻辑从这儿开始。*_dialog.py和*_dialog_base.ui是界面部分。.ui文件是 Qt Designer 的格式可以用Qt Designer打开拖控件也可以用文本编辑器直接改 XML。生成的*_dialog.py会把.ui加载进来同时给你一个run()方法这是你写业务逻辑的地方。注意.ui改完不需要重新生成.py因为它是在运行时加载的这跟resources.qrc的情况不同。resources.qrc和resources.py是资源打包。.qrc里记录图标等资源文件的路径.py是编译后的结果代码里通过:/plugins/...这种形式引用。改完.qrc必须重新编译。Makefile和i18n/是给pb_tool和翻译用的初始阶段可以不管。4.3 资源文件与 pyrcc5以及 pb_tool 能省多少事资源编译是很多新手第一次改图标时踩的坑把新图标拷进目录、在.qrc里改了路径但界面上还是旧图标。原因就是没重新编译.qrc。编译命令是call C:\Program Files\QGIS 3.34.0\bin\o4w_env.bat pyrcc5 -o resources.py resources.qrcpyrcc5是 PyQt5 附带的资源编译器在o4w_env.bat设好环境后直接在命令行可用。如果你的 QGIS 版本用的是 Qt6 路线对应的命令可能换成pyrcc6或者已经不再需要这一步Qt6 更推荐用文件系统直接加载图标以你机器上有哪个命令为准敲pyrcc5 --help试一下就知道。手工敲pyrcc5当然可以但插件项目通常还要做别的重复劳动把插件部署到 profile 目录、打包成 zip、清理临时文件、更新翻译。这些琐事可以用pb_tool一次性解决。它在 QGIS 的 Python 环境里安装call C:\Program Files\QGIS 3.34.0\bin\o4w_env.bat python -m pip install pb_tool然后在插件目录下运行pb_tool compile REM 编译 .qrc 和 .ui pb_tool deploy REM 部署到 profile 目录 pb_tool zip REM 打包成可发布的 zip pb_tool clean REM 清理中间产物pb_tool读取插件目录里的pb_tool.cfg判断各项参数。Plugin Builder 生成的目录一般已经带了这个配置文件如果没带运行pb_tool create生成一个。提示pb_tool deploy会覆盖 profile 目录里同名插件。如果你同时手工改过 profile 里的文件部署前先备份免得辛苦改的代码被覆盖。这个坑我踩过不止一次。4.4 Plugin Reloader把改一行重启一次这件事干掉QGIS 启动一次要好几秒改一行代码就重启一次一天下来时间全耗在等待上。Plugin Reloader就是解决这个的。安装方式同样是在插件管理器里搜 Plugin Reloader。装完后菜单里会出现Plugin Reloader → Choose plugin选你的插件然后点Reload plugin。它的工作原理是调用qgis.utils.reloadPlugin()把插件的模块从内存里卸载再重新加载。实测下来它的边界要清楚能热重载的插件的 Python 逻辑代码、.ui文件因为运行时加载、metadata.txt的部分字段。不能热重载的__init__.py的结构性改动、新增的.py文件有可能不被识别、resources.py的改动有时能有时不能稳妥起见还是重启。另外主类的unload()方法必须写对。如果卸载时没把动作从界面移除重载后你会看到菜单里出现两份同样的项点哪个都可能出问题。生成的模板里unload()一般是写好的你自己加动作时记得同步在unload()里清理。还有一个更原生的方式在 QGIS 的 Python 控制台里直接执行import qgis.utils qgis.utils.reloadPlugin(my_first_plugin)效果和 Plugin Reloader 一样但胜在快可以把它绑定到一段你自己的小脚本里。5. 调试、排错与打包从能跑到能发5.1 断点调试的可行做法插件调试比普通脚本麻烦因为代码运行在 QGIS 进程里你不能直接在编辑器里按 F5 启动调试。目前可行的做法有两条。第一条是远程附加调试。原理是让 QGIS 进程里跑起一个调试服务端编辑器作为客户端附加过去。以debugpy为例先把它装到 QGIS 的 Python 环境call C:\Program Files\QGIS 3.34.0\bin\o4w_env.bat python -m pip install debugpy然后在 QGIS 的 Python 控制台里执行import debugpy debugpy.listen((127.0.0.1, 5678)) print(waiting for debugger...)接着在 VS Code 里配一个 attach 配置{ name: Attach to QGIS, type: debugpy, request: attach, connect: { host: 127.0.0.1, port: 5678 }, pathMappings: [ { localRoot: ${workspaceFolder}/my_first_plugin, remoteRoot: C:\\Users\\用户名\\AppData\\Roaming\\QGIS\\QGIS3\\profiles\\default\\python\\plugins\\my_first_plugin } ] }路径映射这一项是关键两边的目录必须能对上否则断点会显示为未绑定。启动 attach 之后你在插件里加的断点就能命中了。第二条是日志法也就是最土但最有效的办法。在代码里插打印或者把异常信息写进 QGIS 的日志面板from qgis.core import QgsMessageLog, Qgis def run(self): try: # 你的业务逻辑 pass except Exception as e: import traceback QgsMessageLog.logMessage(traceback.format_exc(), MyPlugin, Qgis.Critical)QgsMessageLog会把消息写进 QGIS 的日志消息面板菜单里可以打开出错时带上完整堆栈比单行 print 有用得多。开发期把print和QgsMessageLog混着用效率最高。5.2 报错定位的顺序先看这里再看那里排查插件问题有一套固定顺序照着走能省很多时间。第一步看插件到底有没有被加载。在 QGIS 的 Python 控制台里执行import qgis.utils print(qgis.utils.plugins.keys())如果你的插件模块名不在里面说明加载就失败了问题在metadata.txt或__init__.py。如果在里面但功能不对说明加载成功问题在业务逻辑。第二步看 QGIS 启动时的日志。菜单里的日志消息面板会记录插件加载异常。很多时候你以为插件没加载其实加载了但initGui里抛了异常QGIS 捕获后没弹窗。第三步检查路径。qgis.utils.plugin_paths()的输出里必须包含你的插件所在目录。如果插件放在自定义目录要去设置 → 选项 → 系统 → 插件路径里手工加进去。第四步检查版本门槛。metadata.txt里的qgisMinimumVersion高于当前 QGIS 版本时插件会直接不显示且几乎不给提示。这是最阴的一个坑。第五步看是否有命名冲突。插件模块名如果和已安装的其他 Python 包重名比如叫test、utils导入时可能被解析到别的模块上表现为代码明明改了却没变化。5.3 跨版本兼容与 Python 版本差异QGIS 3.x 系列内部是 PyQt5但 Python 版本在系列内部有过变化。早期 3.x 版本多用 Python 3.6/3.7LTR 阶段常见 3.9较新的版本开始用 3.12。这个差异会直接影响到你的代码能不能跑语法层面3.12 里一些被弃用的写法会警告甚至报错比如某些datetime用法、imp模块。你如果在 3.12 上开发却想兼容 3.9就避免使用 3.10 才有的语法特性比如match语句。API 层面QGIS 的 API 在不同小版本间会做弃用调整。以前能用的QgsGeometry.fromPolygon()这类方法新版本会推荐换成QgsGeometry.fromPolygonXY()旧方法可能还能用但会告警。打包层面如果你想同时在多个 QGIS 版本上测试最省事的方法是装多个版本的 QGIS 到不同的目录用不同 profile 隔离配置。实际做法上我建议以 LTR 版本为开发基准然后在metadata.txt里把qgisMinimumVersion设成你真正测过的最低版本。别为了兼容很老的版本去牺牲代码可读性社区主流用户都在 LTR 及以上。5.4 上架前的自检清单插件写完了要发布或交付之前这套清单过一遍能挡掉大部分低级问题。检查项具体要求常见失误metadata.txt完整性name、version、description、author、email、qgisMinimumVersion 必填缺 email 或 version 格式不规范version递增每次发布必须比上一次大直接覆盖发布导致仓库拒绝experimental状态正式发布设为 False忘了改用户看不到插件图标引用正确图标路径与.qrc编译结果一致改了图但没重新 pyrcc5依赖声明如果用了额外 pip 包要在about或文档里说明用户装上后 ImportError卸载干净unload()里移除所有添加的动作和界面元素重载后出现重复菜单项中英文资源有翻译需求时补齐.ts并 lrelease 编译翻译文件没编译界面还是英文异常兜底关键路径加 try/except 并写 QgsMessageLog出错时用户完全不知道为什么打包成 zip 之后自己先在一台干净的机器上或者一个新建的 profile 里装一遍。这一步能发现在我机器上没问题这类隐蔽问题比如某个路径写死成了你的用户名。6. 几个我反复踩的坑和顺手的小习惯6.1 中文路径、空格与权限这三个问题在 Windows 上出现频率最高。中文路径的问题出在编码环节。有些工具链在读取.qrc、.ts、.ui这些 XML 文件时对非 ASCII 路径的处理不一致表现为编译报错或者资源加载不出来。最省事的规避办法是把整个开发链路放在纯英文路径下包括 QGIS 安装目录、编辑器工作区、插件目录里的用户名的部分。用户目录带中文这一点比较麻烦因为%APPDATA%是 Windows 给定的。如果你的用户名是中文C:\Users\张三\AppData\...就会带中文。规避方式是新建一个英文名的用户或者把插件开发目录放在D:\qgis-dev\这种纯英文路径下只把编译产物部署到 profile 目录。命令行引用带空格路径时所有路径都要加双引号包括o4w_env.bat的路径。权限问题上C:\Program Files\下的文件默认不可写。装插件不需要写安装目录所以一般不冲突但如果你想改 QGIS 自带的 Python 库文件不建议会碰到权限拒绝。pip install装到 QGIS Python 环境时如果报权限错误说明装到了系统级的Program Files目录下这时候要么用管理员权限要么加--user装到用户目录。6.2 环境变量顺序与两个 Python 打架PATH的顺序决定命令解析的结果。如果你系统里同时有 Anaconda、微软商店版 Python、QGIS 自带 Python敲python和pip时到底用哪个完全取决于PATH里谁在前面。插件开发时这个问题的表现是你在终端里敲python启动的却是 Anaconda然后import qgis.core报错你以为是 QGIS 环境坏了其实是走错解释器了。判断方法很简单敲where python where pip输出的第一行就是实际生效的那个。确认是 QGIS 目录下的再往下做。根治方法是不要把这个混乱留给环境变量而是记住一条规矩涉及 QGIS 的操作永远先在终端里执行o4w_env.bat这个脚本会把 QGIS 相关的路径插到PATH前面压制掉其他 Python。养成这个习惯能避免大量明明配好了却报错的困惑。6.3 改了代码没生效的三层原因这个现象我遇到过三种完全不同的成因排查顺序是从外到内。第一层代码没到 QGIS 会读取的位置。你在编辑器工作区改的是源目录里的文件但 QGIS 加载的是 profile 目录下的插件。这两个目录如果没做链接或同步改了源目录等于没改。解决办法是用pb_tool deploy同步或者在 profile 目录里做符号链接Windows 下用mklink /D。第二层代码到了但模块没重新加载。Python 的模块一旦被导入就缓存在sys.modules里改文件不会自动重新执行。所以要么用 Plugin Reloader要么在 Python 控制台里调qgis.utils.reloadPlugin()。注意新加的文件有时热重载识别不到这种情况还是得重启。第三层代码加载了但走的是缓存。这种最少见但最迷惑.pyc缓存文件、或者插件自己在某个地方存了配置/状态导致看起来行为没变。清掉插件目录下的__pycache__文件夹重启 QGIS基本能解决。一个顺手的小习惯在插件主类的initGui里加一行版本日志QgsMessageLog.logMessage(MyPlugin v0.1.3 loaded, MyPlugin)每次重载后看一眼日志里的版本号就知道到底加载的是不是最新代码。这一行花费几秒钟省下的排查时间是以小时计的。6.4 多版本 QGIS 共存时的切换办法如果你的工作需要同时维护面向不同 QGIS 版本的插件多版本共存是必须的。安装时把不同版本装到不同目录比如C:\Program Files\QGIS 3.28.0\和C:\Program Files\QGIS 3.34.0\互不干扰。切换的关键在 profile。不同版本的 QGIS 使用的 profile 目录其实是可以共用的都在%APPDATA%\QGIS\QGIS3\下但共享 profile 会导致插件列表和设置混在一起。更干净的做法是给每个版本建独立 profileC:\Program Files\QGIS 3.28.0\bin\qgis-ltr-bin.exe --profile qgis328 C:\Program Files\QGIS 3.34.0\bin\qgis-ltr-bin.exe --profile qgis334这样两个版本的配置完全隔离插件各自装各自的。开发插件时同一个源目录可以通过pb_tool分别部署到两个 profile 的插件目录下测试一遍就能确认跨版本兼容性。编辑器这边的处理是为每个 QGIS 版本建一个独立的 VS Code 工作区settings.json里的解释器路径、extraPaths分别指向对应版本的目录。切工作区就等于切环境避免手工改路径。最后再提一个容易被忽略的点profile 名字一旦确定就别随便改。改了之后 QGIS 会当成一个全新的 profile之前的插件启用状态、界面布局全丢你会以为出问题了。我个人在这个话题上的体会是QGIS 插件开发的环境配置难点不在于步骤多而在于环境是外部给的这件事。普通 Python 项目里你几乎不需要关心解释器怎么来的而这里必须把解释器、环境变量、加载路径这三件事想明白。想明白之后配置本身十分钟就能做完想不明白的话可能折腾一整天还在报同一个错。所以我通常建议新手先花半小时把o4w_env.bat里到底设了哪些变量打印出来看一遍那几十行输出比任何教程都直观。