让 QGIS 对 Agent 原生可用:cli-anything-qgis 状态化 CLI 与 PyQGIS / qgis_process 双后端实战指南
2026/9/8 18:38:21 网站建设 项目流程

让 QGIS 对 Agent 原生可用:cli-anything-qgis 状态化 CLI 与 PyQGIS / qgis_process 双后端实战指南

【免费下载链接】CLI-Anything"CLI-Anything: Making ALL Software Agent-Native" -- CLI-Hub: https://clianything.cc/项目地址: https://gitcode.com/GitHub_Trending/cl/CLI-Anything

cli-anything-qgis是 CLI-Anything 生态中面向 QGIS 的智能体(Agent)操作网关,它直接驱动机器上已安装的真实 QGIS 运行时,把“建工程、建图层、写要素、排版式、导出文件、跑地理处理算法”全部封装为稳定、可复现、默认输出 JSON 的命令。本文以 QGIS/agent-harness/cli_anything/qgis/README.md 为骨架,结合仓库内 架构说明、CLI 入口实现 与 core 模块 源码,完整讲解安装、命令用法、运行时分工与底层实现机制。读完本文,你将能够在一行命令内完成 QGIS 项目编写到 PDF/图片导出的完整 GIS 数据流水线,也能理解该 harness 如何用 PyQGIS 保持有状态、用qgis_process --json兜底通用算法执行。

它到底能做什么

README 定义了六个核心能力面,全部运行在真实 QGIS 运行时之上:

  • 使用 PyQGIS 管理.qgs/.qgz工程文件;
  • 创建可写的 GeoPackage 后备矢量图层
  • 通过WKT 几何添加并检视要素;
  • 编写简单打印版式(print layout),包括地图项与文本标签项;
  • 通过qgis_process --json导出版式(PDF / 图片);
  • 暴露通用 QGIS 地理处理(processing)算法的发现与执行能力;
  • 所有命令均支持机器可读的--json输出;
  • 不带子命令运行时进入有状态 REPL

换言之,CLI 覆盖了一条完整的矢量 GIS 生产链:工程 → 图层 → 要素 → 版式 → 导出 → 算法处理

运行时模型:一次“双后端”职责切分

仓库架构文档 QGIS/agent-harness/QGIS.md 明确了设计上刻意保持的分工:

  • PyQGIS 负责有状态创作(authoring):工程的新建/打开/保存、CRS 与标题修改、可写矢量图层创建、要素插入、版式创建与条目编辑、面向 CLI 输出的工程/图层/版式摘要。这些都操作或检查进程内的 QGIS 工程对象QgsProject.instance())。
  • qgis_process --json负责通用算法与导出:算法发现(list)、算法帮助(help <id>)、通用算法执行(run <id>)、版式 PDF 导出(native:printlayouttopdf)、版式图片导出(native:printlayouttoimage)。这些已经有 QGIS 官方支持的稳定 CLI 契约(含 JSON 输出与算法元数据),因此不需要在 Python 里重新实现后端逻辑。

这样做的收益在源码中清晰可见:需要跨命令保存实时工程状态的操作(REPL 场景)走 PyQGIS;而 QGIS 已把“算法元数据 + JSON”作为一等公民暴露的场景则直接透传,让 harness 尽量贴近 QGIS 本身。值得说明的是,本 harness不是QGIS/src自动生成的,而是调研 QGIS 稳定运行时表面后手工圈定的一组可测试子集:project/layer/feature/layout包装 PyQGIS,export/process包装qgis_processsession则是 harness 自身用于 REPL 与命令历史的轻量会话功能。

环境准备与安装

前置条件

README 列出了三条硬性前提:

  • 已安装 QGIS,且qgis_processPATH中;
  • 运行本包所用的 Python 能够importPyQGIS;
  • Python 3.10+(setup.py 中python_requires=">=3.10")。

用以下快速检查确认环境就绪:

qgis_process --version python3 -c "from qgis.core import QgsApplication; print('pyqgis-ok')"

底层代码 qgis_backend.py 对 QGIS 前缀做了自适应:先读环境变量QGIS_PREFIX_PATH,否则从qgis_process/qgis可执行文件路径反推安装前缀,最后兜底为/usr,再通过QgsApplication.setPrefixPath(..., True)初始化单例 QGIS 应用。因此只要 PyQGIS 可导入,通常无需手工配置前缀。

安装命令

cd QGIS/agent-harness python3 -m pip install -e .

如果 PyQGIS 来自系统包,普通虚拟环境可能看不到qgisPython 模块。README 给出的解法是启用系统 site-packages 后重建虚拟环境

python3 -m venv --system-site-packages .venv . .venv/bin/activate python3 -m pip install -e .

安装后验证:

which cli-anything-qgis cli-anything-qgis --help cli-anything-qgis --json process help native:printlayouttopdf

其中cli-anything-qgis可执行文件由 setup.py 的entry_points注册到包入口cli_anything.qgis.qgis_cli:main;运行期仅依赖click>=8.0.0prompt-toolkit>=3.0.0。上述--json process help native:printlayouttopdf命令同时验证了安装与qgis_processJSON 通路是否畅通。

一次性命令:跑通“工程 → 图层 → 要素 → 版式 → 导出”流水线

以下命令来自 README 并保持原样,构成最小可运行的端到端示例。

创建工程(立即落盘保存):

cli-anything-qgis --json project new -o demo.qgz --title "Demo" --crs EPSG:4326

在工程的 sidecar GeoPackage 中创建可写图层

cli-anything-qgis --json --project demo.qgz layer create-vector \ --name places \ --geometry point \ --field name:string \ --field score:int

按 WKT 添加要素(可重复--attr key=value):

cli-anything-qgis --json --project demo.qgz feature add \ --layer places \ --wkt "POINT(1 2)" \ --attr name=HQ \ --attr score=5

创建版式并添加条目

cli-anything-qgis --json --project demo.qgz layout create --name Main # Auto extent should work even for point-only projects; pass --extent only when you want explicit framing. cli-anything-qgis --json --project demo.qgz layout add-map --layout Main --x 10 --y 20 --width 180 --height 120 cli-anything-qgis --json --project demo.qgz layout add-label --layout Main --text "Demo map" --x 10 --y 8 --width 120 --height 10

注意 add-map 示例中对点要素工程同样可用:源码 layouts.py 中,未显式传--extent时会用_combined_project_extent()把所有图层范围合并,纯点图层(宽高为 0)会被extent.grow(1.0)向外扩 1 个单位,避免退化为空范围。需要显式框定时再传--extent xmin,ymin,xmax,ymax

经真实 QGIS 后端导出

cli-anything-qgis --json --project demo.qgz export pdf output.pdf --layout Main --overwrite cli-anything-qgis --json --project demo.qgz export image output.png --layout Main --overwrite

检视与执行地理处理算法

cli-anything-qgis --json process list cli-anything-qgis --json process help native:buffer cli-anything-qgis --json --project demo.qgz process run native:buffer \ --param INPUT=places \ --param DISTANCE=10 \ --param SEGMENTS=8 \ --param END_CAP_STYLE=0 \ --param JOIN_STYLE=0 \ --param MITER_LIMIT=2 \ --param DISSOLVE=false \ --param OUTPUT=/tmp/buffer.gpkg

关键约定:process run通过可重复的--param KEY=VALUE传参,算法参数与 QGIS 处理算法原生命名完全一致;没有--projectprocess list/process help是纯环境级操作,不需要打开工程。这也印证了架构边界:算法可以直接针对 shapefile 或其他数据源路径执行,不必先纳入工程。

有状态 REPL:不带子命令直接进入

运行:

cli-anything-qgis

即进入默认的 REPL 模式(qgis_cli.py 中无子命令且非--help时自动调用repl)。README 给出的示例会话:

project new -o demo.qgz --title "Demo" layer create-vector --name places --geometry point --field name:string feature add --layer places --wkt "POINT(1 2)" --attr name=HQ layout create --name Main layout add-map --layout Main --x 10 --y 20 --width 180 --height 120 export pdf demo.pdf --layout Main --overwrite session status quit

REPL 中的每一行都会被shlex.split后重新派发给同一套 click 命令组执行,因此一次性模式与 REPL 模式共享全部命令与参数语义。会话还支持helpexit/q;提示符皮肤(repl_skin.py)会在输入行展示当前工程名与修改状态(dirty 标记),帮助 Agent 感知“改动是否已保存”。一次性命令默认会自动保存改动(_auto_save_if_one_shot),而 REPL 模式下改动保存在内存工程中,可通过显式project save或在export时触发的save_if_dirty落盘。

命令组参考

CLI 一共七组命令(qgis_cli.py 中同名字命令组):

命令组子命令作用
projectnew/open/save/info/set-crs新建并立即保存工程、打开既有工程、保存当前工程、检视当前工程、修改工程 CRS
layercreate-vector/list/info/remove创建 GeoPackage 后备矢量图层、列出工程图层、检视单图层、从工程移除图层
featureadd/list用 WKT 几何与key=value属性添加要素、检视图层要素
layoutcreate/list/info/remove/add-map/add-label创建打印版式、列出/检视/删除版式、添加地图项、添加文本标签项
exportpresets/pdf/image列出受支持的导出模式、以 PDF 导出版式、以图片导出版式
processlist/help/run列出已安装处理算法、检视算法参数与输出、以可重复--param KEY=VALUE执行算法
sessionstatus/history检视当前会话状态、检视近期命令历史

结合 CLI 源码,各子命令的实用参数与默认值如下:

  • project new-o/--output必填;--title缺省用文件名;--crs缺省EPSG:4326。路径规范化由 project.py 的normalize_project_path完成:无扩展名默认补.qgz,支持.qgs/.qgz两种格式。
  • layer create-vector--name--geometry必填;--geometry仅接受point/linestring/polygon(大小写不敏感,line亦被映射为 LineString);--crs缺省继承工程 CRS;--field可重复,格式name:type
  • 字段类型映射表(layers.py):CLI 输入简单类型 → QGISQMetaType原生类型:
CLI 字段类型规范化类型QMetaType
int/integerintegerInt
double/floatdoubleDouble
string/strstringQString
bool/booleanboolBool
  • feature list--limit缺省 20,--layer可按图层 id 或精确名称解析。
  • layout create--page-size缺省A4,合法值A4/A3/A2/A1/A0/LETTER--orientation缺省portrait,可选landscape
  • layout add-map--x/--y/--width/--height均为毫米单位必填;--extent可覆盖自动范围。
  • layout add-label:额外--font-size缺省18.0磅。
  • export pdf--layout必填;--dpi覆盖版式 DPI;--force-vector强制矢量输出;--force-raster强制栅格化 PDF;--georeference/--no-georeference缺省为开启(追加地理参考元数据);--overwrite覆盖已存在文件。
  • export image--dpi--overwrite;输出格式如 PNG。
  • process run:算法参数统一经--param传入;工程上下文经全局--project绑定。
  • 全局选项:--json(机器可读 JSON)与--project(为当前命令打开某工程),对所有命令组生效。

数据模型与底层实现细节

工程与 sidecar GeoPackage

工程保存即落盘;无扩展名输出名默认规范化为.qgz新建图层默认使用工程的 sidecar GeoPackage,路径规则见 project.py 的default_datastore_path

  • demo.qgz→ 同目录demo_data.gpkg

也就是说demo.qgz会配一个demo_data.gpkg,这让作者数据常驻磁盘,后续process runexport都能针对真实数据集工作。图层创建链路是“先建内存图层 → 用QgsVectorFileWriter.writeAsVectorFormatV3写入 GPKG → 以ogrprovider 重新打开并addMapLayer入工程”。既有 GPKG 文件存在时以CreateOrOverwriteLayer行为新增图层;图层重名会直接报错。

要素写入与属性类型强转

要素插入只接受两类输入:WKT 几何 + 可重复的--attr key=value。架构文档说明:属性值会按图层声明的 QGIS 字段类型做类型强制(coerce),CLI 输入保持简单字符串,而存储层 schema 保持权威——这正是“简单输入 + 强 schema”的 agent 友好设计。

版式的“窄而可用”范围

v1 刻意只实现小而实用的版式面:创建/删除/列出版式、添加地图项、添加标签项、自动从工程图层推导地图范围。这与“用整块桌面版式系统”保持边界,避免 harness 膨胀。各布局项位置与尺寸单位固定为毫米(QgsUnitTypes.LayoutMillimeters)。

导出链路:先保真再交给原生算法

导出实现在 export.py:

  1. get_layout(name)校验版式存在;
  2. save_if_dirty()保证工程最新状态落盘(有--project或 dirty 才写);
  3. 校验输出路径(已存在且无--overwrite时报错);
  4. 组装算法参数并交给qgis_process
  • PDF:LAYOUT=...OUTPUT=...FORCE_VECTOR=true|falseFORCE_RASTER=true|falseGEOREFERENCE=true|false、可选DPI=...,算法native:printlayouttopdf
  • 图片:LAYOUTOUTPUT、可选DPI,算法native:printlayouttoimage

返回结果包含formatlayoutoutput实际file_size、工程摘要、算法的resultslog,方便 Agent 直接断言导出是否成功。

export presets子命令返回当前两个受支持模式及其后端算法 id,可作为 Agent 的运行时能力自检入口。

JSON 输出契约与错误模型

所有命令都支持--json输出(qgis_cli.py 的output()统一json.dumps(indent=2, default=str)),人类可读输出仅是次要选择。错误被归一为稳定 JSON 结构:error(消息)、type(异常类名),若来自qgis_process还会附上returncodestderrstdoutpayload(qgis_backend.py 的QgisProcessError)。底层run_process_json()会拼装qgis_process --json <args> [--PROJECT_PATH=...] -- <params>并解析 stdout 为 dict;qgis_process非零退出时从 log/results 中抽取可读消息上抛。因此Agent 面对失败也能拿到结构化原因,而不是一坨 stderr。

会话模型

会话状态存于~/.cli-anything-qgis/session.json(由 session.py 维护),内容包括:当前工程路径、modified 标记、命令历史。session status会同步工程路径并报告 dirty 状态;session history --limit 20查看最近命令。REPL 是默认入口,一次性命令用--project把命令绑定到已保存工程。

给 Agent / LLM 的使用建议

README 的官方指引非常明确:除非人类可读摘要确实更合适,否则一律优先--json。这保证了输出结构可解析、可断言。对自动化流程,推荐按以下模式组织:

  1. --json process help <algo>先查算法签名,再拼--param,避免猜参数;
  2. 导出类命令务必核对返回里的file_size/results.OUTPUT确认真实产物生成;
  3. 跨多个命令持续编辑时,要么用 REPL 保状态,要么每次带--project并在收尾执行project save
  4. export presetsprocess list作为运行环境能力探测,快速判断该机器 QGIS 是否可用。

测试与验证策略

测试入口(README)与目录 QGIS/agent-harness/cli_anything/qgis/tests 对应:

python3 -m pytest cli_anything/qgis/tests/test_core.py -v python3 -m pytest cli_anything/qgis/tests/test_full_e2e.py -v -s

QGIS.md 描述的测试策略覆盖三层:(1) 直接针对 PyQGIS 辅助函数的模块级单测;(2) 针对真实 QGIS 运行时的端到端 E2E 流程;(3) 针对已安装cli-anything-qgis可执行文件的子进程测试——同时检验库层逻辑与打包/运行时契约。仓库内 pytest.ini 使用--import-mode=importlib配合命名空间包布局。安装-e .时还可通过extras_require["dev"]引入pytestpytest-covjinja2

已知边界(源码确认)

按 QGIS.md 的明确记录,当前 harness 有意的边界包括:只暴露小型版式子集而非完整桌面版式系统;可直接对 shapefile 等数据源路径执行算法,但目前没有一等公民命令把任意既有 shapefile 加入工程。理解这些边界能避免 Agent 在超出设计范围的诉求上浪费调用。

延伸阅读

  • 架构说明与 API 对照:QGIS/agent-harness/QGIS.md
  • CLI 完整命令与全局选项实现:qgis_cli.py
  • PyQGIS /qgis_process底层封装:qgis_backend.py
  • 领域核心模块:core/project.py、core/layers.py、core/layouts.py、core/export.py
  • Agent 可直接装载的技能描述:skills/cli-anything-qgis/SKILL.md
  • 打包元数据与依赖:QGIS/agent-harness/setup.py

【免费下载链接】CLI-Anything"CLI-Anything: Making ALL Software Agent-Native" -- CLI-Hub: https://clianything.cc/项目地址: https://gitcode.com/GitHub_Trending/cl/CLI-Anything

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询