znlgis 博客

GIS开发与技术分享

第三章:快速上手——第一个流水线

3.1 学习目标

通过本章,你将:

  1. 编写并运行第一个 YAML 流水线。
  2. 理解流水线的基本结构(变量、步骤、输出)。
  3. 解读 JSON 执行报告。
  4. 了解常用的 CLI 命令。

3.2 准备测试数据

本章使用一个简单的 GeoJSON 文件作为测试数据。如果你手边没有 GIS 数据,可以用以下方式快速创建一个:

# 在 Python 中生成测试数据(可选)
import geopandas as gpd
from shapely.geometry import LineString, Point

# 创建几条模拟道路线段
roads = gpd.GeoDataFrame({
    'name': ['路段A', '路段B', '路段C'],
    'type': ['主干道', '次干道', '支路'],
    'geometry': [
        LineString([(116.3, 39.9), (116.4, 39.9)]),
        LineString([(116.4, 39.9), (116.4, 40.0)]),
        LineString([(116.3, 40.0), (116.4, 40.0)]),
    ]
}, crs="EPSG:4326")

roads.to_file("data/roads.geojson", driver="GeoJSON")
print("测试数据已生成:data/roads.geojson")

保存为 prepare_data.py 并执行:

mkdir -p data
python prepare_data.py

3.3 编写第一个流水线

创建文件 my-first-pipeline.yaml

name: 道路缓冲区分析
description: 对道路数据进行坐标系转换后做缓冲区分析,并将结果保存为 GeoJSON

variables:
  input_path: "data/roads.geojson"
  buffer_dist: 200

steps:
  - id: load-roads
    use: io.read_vector
    params:
      path: ${input_path}

  - id: reproject
    use: vector.reproject
    params:
      input: $load-roads
      target_crs: "EPSG:3857"

  - id: buffer
    use: vector.buffer
    params:
      input: $reproject
      distance: ${buffer_dist}
      cap_style: round

  - id: save-result
    use: io.write_vector
    params:
      input: $buffer
      path: "output/roads_buffer.geojson"
      driver: GeoJSON

outputs:
  buffer_result: $save-result

流水线结构解析

字段 说明
name 流水线名称,用于报告和日志显示
description 可选的流水线描述
variables 定义可复用的变量,可被 ${var} 引用,也可通过 CLI --var 参数覆盖
steps 步骤列表,按顺序执行
outputs 输出声明,将步骤结果映射到具名输出

每个步骤的字段:

字段 必填 说明
id 步骤唯一标识,只允许字母、数字、下划线、短横线
use 步骤类型,格式为 类别.动作(如 io.read_vector
params ⚠️ 步骤参数,各步骤参数不同
when 条件表达式,为 false 时跳过
on_error 错误策略:fail / skip / retry
backend 指定后端,默认 native_python

3.4 执行流水线

# 创建输出目录
mkdir -p output

# 执行流水线
geopipe-agent run my-first-pipeline.yaml

正常执行时,终端会输出类似以下内容:

[INFO] 🚀 开始执行流水线:道路缓冲区分析
[INFO] 执行步骤 [1/4]: load-roads (io.read_vector)
[INFO] ✅ load-roads 完成(耗时 0.12s)
[INFO] 执行步骤 [2/4]: reproject (vector.reproject)
[INFO] ✅ reproject 完成(耗时 0.08s)
[INFO] 执行步骤 [3/4]: buffer (vector.buffer)
[INFO] ✅ buffer 完成(耗时 0.05s)
[INFO] 执行步骤 [4/4]: save-result (io.write_vector)
[INFO] ✅ save-result 完成(耗时 0.09s)
[INFO] 🎉 流水线执行完成(总耗时 0.34s)

执行完成后,output/roads_buffer.geojson 即为缓冲区分析结果。

3.5 解读 JSON 执行报告

除了终端日志,每次执行还会生成一个 JSON 格式的结构化报告,打印到标准输出(可通过 > 重定向到文件):

geopipe-agent run my-first-pipeline.yaml > report.json

report.json 的内容结构如下:

{
  "pipeline": {
    "name": "道路缓冲区分析",
    "description": "对道路数据进行坐标系转换后做缓冲区分析,并将结果保存为 GeoJSON",
    "executed_at": "2024-01-15T10:30:00.000Z",
    "total_duration_seconds": 0.34,
    "status": "success"
  },
  "steps": [
    {
      "id": "load-roads",
      "use": "io.read_vector",
      "status": "success",
      "duration_seconds": 0.12,
      "stats": {
        "feature_count": 3,
        "crs": "EPSG:4326"
      }
    },
    {
      "id": "reproject",
      "use": "vector.reproject",
      "status": "success",
      "duration_seconds": 0.08,
      "stats": {
        "feature_count": 3,
        "source_crs": "EPSG:4326",
        "target_crs": "EPSG:3857"
      }
    },
    {
      "id": "buffer",
      "use": "vector.buffer",
      "status": "success",
      "duration_seconds": 0.05,
      "stats": {
        "feature_count": 3,
        "distance": 200,
        "cap_style": "round"
      }
    },
    {
      "id": "save-result",
      "use": "io.write_vector",
      "status": "success",
      "duration_seconds": 0.09,
      "stats": {
        "path": "output/roads_buffer.geojson",
        "feature_count": 3
      }
    }
  ],
  "outputs": {
    "buffer_result": {
      "type": "file",
      "path": "output/roads_buffer.geojson"
    }
  }
}

JSON 报告的主要字段说明:

  • pipeline.status:整体执行状态(success / failed
  • steps[].status:各步骤状态(success / skipped / failed
  • steps[].stats:各步骤的统计信息,不同步骤内容不同
  • outputs:输出声明对应的实际结果

3.6 通过 CLI 参数覆盖变量

流水线中的变量支持在运行时通过 --var 参数覆盖,实现同一 YAML 文件的复用:

# 覆盖 input_path 和 buffer_dist 变量
geopipe-agent run my-first-pipeline.yaml \
  --var input_path=data/rivers.shp \
  --var buffer_dist=1000

这在批处理场景下非常有用:同一个流水线可以处理不同的数据文件或参数组合。

3.7 校验流水线(不执行)

在实际执行之前,可以先用 validate 命令检查 YAML 语法和配置是否正确:

geopipe-agent validate my-first-pipeline.yaml

validate 命令会检查:

  • YAML 语法是否合法
  • 必填字段是否齐全
  • 步骤 ID 是否唯一
  • 步骤引用($step-id)是否存在
  • 步骤类型(use)是否是已注册的步骤

校验通过示例输出:

✅ 流水线校验通过
  - 步骤数量: 4
  - 变量数量: 2
  - 输出数量: 1

3.8 查看数据文件信息

在处理数据之前,可以用 info 命令快速了解 GIS 文件的基本信息:

geopipe-agent info data/roads.geojson

输出示例:

{
  "path": "data/roads.geojson",
  "type": "vector",
  "driver": "GeoJSON",
  "crs": "EPSG:4326",
  "feature_count": 3,
  "geometry_type": "LineString",
  "bbox": [116.3, 39.9, 116.4, 40.0],
  "columns": ["name", "type"]
}

3.9 查看步骤文档

不确定某个步骤的参数时,可以用 describe 命令查看详细文档:

# 查看 vector.buffer 步骤的说明和参数
geopipe-agent describe vector.buffer

输出示例:

步骤: vector.buffer
类别: vector
名称: 缓冲区分析

描述:
  对矢量要素进行缓冲区分析,生成缓冲面(Polygon)。
  输入可以是任意几何类型,输出始终为 Polygon 或 MultiPolygon。

参数:
  input     (必填) 输入 GeoDataFrame(来自前一步骤的引用)
  distance  (必填) 缓冲距离,单位与 CRS 一致
  cap_style (可选) 端点样式:round(圆头)/ flat(平头)/ square(方头),默认 round
  join_style (可选) 拐角样式:round / mitre / bevel,默认 round

示例:
  - id: buffer
    use: vector.buffer
    params:
      input: $load
      distance: 500
      cap_style: round

3.10 完整示例:Cookbook 中的流水线

cookbook/ 目录中提供了多个即用型示例,以 buffer-analysis.yaml 为例:

# cookbook/buffer-analysis.yaml
name: 缓冲区分析示例
description: 完整的缓冲区分析流水线,包含读取、投影、缓冲、保存四步

variables:
  input_path: "data/sample_roads.shp"
  output_path: "output/buffer_result.geojson"
  buffer_distance: 500
  target_crs: "EPSG:3857"

steps:
  - id: read-data
    use: io.read_vector
    params:
      path: ${input_path}

  - id: reproject
    use: vector.reproject
    params:
      input: $read-data
      target_crs: ${target_crs}

  - id: create-buffer
    use: vector.buffer
    params:
      input: $reproject
      distance: ${buffer_distance}
      cap_style: round

  - id: save-result
    use: io.write_vector
    params:
      input: $create-buffer
      path: ${output_path}
      driver: GeoJSON

outputs:
  result: $save-result

运行示例:

geopipe-agent run cookbook/buffer-analysis.yaml

3.11 常见错误与排查

错误 1:步骤引用不存在

❌ 步骤 'buffer' 的参数 'input' 引用了不存在的步骤 '$load-roads'

原因:步骤 id 拼写错误,或引用的步骤定义在当前步骤之后。

解决:检查 id 是否一致,确保被引用步骤在当前步骤之前定义。

错误 2:变量未定义

❌ 变量 '${input_path}' 未在 variables 中定义

解决:在 variables 块中定义该变量,或通过 --var input_path=value 在命令行传入。

错误 3:步骤类型不存在

❌ 步骤类型 'vector.bufffer' 未注册(是否拼写错误?)

解决:通过 geopipe-agent list-steps 查看正确的步骤名称,注意大小写。

错误 4:输出目录不存在

❌ 无法写入文件 'output/roads_buffer.geojson':目录 'output' 不存在

解决io.write_vector 步骤会自动创建目录。如果仍报错,请手动创建:mkdir -p output

3.12 小结

本章通过一个完整示例演示了 GeoPipeAgent 的核心工作流:

  1. 准备数据
  2. 编写 YAML 流水线(name + variables + steps + outputs
  3. geopipe-agent validate 校验
  4. geopipe-agent run 执行
  5. 解读 JSON 报告
  6. --var 参数覆盖变量实现复用

掌握这些基础后,后续章节将逐步深入介绍每个模块的细节。第四章将全面讲解 YAML 流水线格式的所有字段和高级用法。