第五章:变量系统与步骤引用
GeoPipeAgent 流水线中有两种核心数据传递机制:变量替换(${var})和步骤引用($step-id)。本章深入解析这两种机制的工作原理和使用技巧。
5.1 变量替换:${var_name}
5.1.1 基本用法
在 pipeline.variables 中定义变量,在步骤 params 中用 ${变量名} 引用:
pipeline:
variables:
input_path: "data/roads.shp"
buffer_dist: 500
output_crs: "EPSG:4326"
steps:
- id: load
use: io.read_vector
params:
path: "${input_path}" # → "data/roads.shp"
- id: buffer
use: vector.buffer
params:
input: "$load"
distance: "${buffer_dist}" # → 500 (数值类型)
- id: reproject
use: vector.reproject
params:
input: "$buffer"
target_crs: "${output_crs}" # → "EPSG:4326"
5.1.2 类型保留
当整个参数值是单一 ${var} 引用时,变量的原始 Python 类型被保留:
variables:
buffer_dist: 500 # int
tolerance: 0.001 # float
auto_fix: true # bool
fields: ["name", "type"] # list
# 传入步骤时类型不变
params:
distance: "${buffer_dist}" # → 500 (int)
tolerance: "${tolerance}" # → 0.001 (float)
auto_fix: "${auto_fix}" # → True (bool)
required_fields: "${fields}" # → ["name", "type"] (list)
5.1.3 字符串插值
当 ${var} 嵌入字符串中时,变量被转为字符串拼接:
variables:
project: "highway-2024"
suffix: ".geojson"
params:
path: "output/${project}${suffix}" # → "output/highway-2024.geojson"
layer: "buffer_${project}" # → "buffer_highway-2024"
5.1.4 通过 --var 在命令行覆盖
--var 参数以 key=value 格式传入,值始终是字符串。框架会尝试进行类型转换(字符串→数字/布尔):
# 整数
geopipe-agent run pipeline.yaml --var buffer_dist=1000
# 浮点数
geopipe-agent run pipeline.yaml --var tolerance=0.005
# 布尔值("true"/"1"/"yes" 转为 True)
geopipe-agent run pipeline.yaml --var auto_fix=true
# 字符串路径
geopipe-agent run pipeline.yaml --var input_path=data/new_roads.shp
# 多个变量
geopipe-agent run pipeline.yaml \
--var input_path=data/new.shp \
--var buffer_dist=200 \
--var output_path=output/new_buffer.geojson
注意:通过
--var传入的值优先于 YAML 文件中variables的定义,且会修改PipelineDefinition.variables字典,影响所有引用该变量的步骤。
5.2 步骤引用:$step-id 和 $step-id.attr
5.2.1 步骤引用基础
步骤引用用于将一个步骤的输出传递给后续步骤的参数。格式:
| 语法 | 等价形式 | 含义 |
|---|---|---|
$step-id |
$step-id.output |
步骤的主输出(StepResult.output) |
$step-id.output |
显式写法 | 同上 |
$step-id.stats |
— | 步骤的 stats 字典整体 |
$step-id.feature_count |
— | stats 中的 feature_count 值 |
$step-id.issues_count |
— | stats 中的 issues_count 值(QC 步骤) |
$step-id.issues_gdf |
— | QC 步骤的问题要素 GeoDataFrame |
steps:
- id: load-data
use: io.read_vector
params:
path: "data/roads.shp"
- id: buffer
use: vector.buffer
params:
input: "$load-data" # 等价于 $load-data.output
distance: 500
- id: save
use: io.write_vector
params:
input: "$buffer" # 等价于 $buffer.output
path: "output/result.geojson"
5.2.2 访问统计属性
每个步骤执行后,StepResult.stats 字典的键可直接作为引用属性访问:
steps:
- id: load-data
use: io.read_vector
params:
path: "data/roads.shp"
- id: check-geometry
use: qc.geometry_validity
params:
input: "$load-data"
auto_fix: false
- id: auto-fix
use: qc.geometry_validity
params:
input: "$load-data"
auto_fix: true
# 只有当几何问题数 > 0 时才执行
when: "$check-geometry.issues_count > 0"
outputs:
# 在 outputs 中引用统计数据
total_features: "$load-data.feature_count" # stats.feature_count
bad_geometry: "$check-geometry.issues_count"
5.2.3 StepResult 结构
理解步骤引用需要了解 StepResult 的数据结构:
@dataclass
class StepResult:
output: Any = None # 主输出(GeoDataFrame、文件路径等)
stats: dict = {} # 统计信息(feature_count、crs 等)
metadata: dict = {} # 元数据(driver、bands 等)
issues: list[QcIssue] = [] # QC 问题列表(仅 QC 步骤填充)
属性访问规则:
$step.output→result.output$step.stats→result.stats(返回整个 stats 字典)$step.feature_count→result.stats["feature_count"](先查 stats)$step.crs→result.stats["crs"](然后查 metadata)- 若以上都找不到,抛出
VariableResolutionError
5.2.4 各类步骤的输出结构
IO 步骤(io.read_vector):
StepResult(
output = GeoDataFrame, # 读取的地理数据
stats = {
"feature_count": int,
"crs": str,
"geometry_types": list,
"columns": list,
}
)
引用示例:
$load.output→ GeoDataFrame(传给下一步的input)$load.feature_count→ 要素数量$load.columns→ 属性字段列表
矢量步骤(vector.buffer):
StepResult(
output = GeoDataFrame, # 缓冲区结果 GeoDataFrame
stats = {
"total_area": float, # 缓冲区总面积
}
)
IO 写入步骤(io.write_vector):
StepResult(
output = str, # 输出文件路径(字符串)
stats = {
"feature_count": int,
"output_path": str,
"format": str,
}
)
QC 步骤(qc.geometry_validity):
StepResult(
output = GeoDataFrame, # 原始输入数据(透传)
stats = {
"issues_count": int,
"valid_count": int,
"issues_by_severity": dict,
},
issues = [QcIssue, ...] # 问题列表
)
QC 步骤专有属性:
$check.issues_count→ 问题数量$check.issues_gdf→ 包含问题要素的 GeoDataFrame$check.issues→ QcIssue 对象列表(不可直接序列化,一般不在 YAML 中引用)
5.3 引用解析顺序与规则
context.py 中的引用解析逻辑:
参数值处理顺序:
1. 非字符串值 → 直接返回(保持原类型)
2. 以 "$" 开头且非 "${" → 步骤引用
2a. "$step-id" → 查找 step-id 的 output
2b. "$step-id.attr" → 查找 step-id 的 stats/metadata 中的 attr
3. 包含 "${" → 变量替换
3a. 整个值是 "${var}" → 返回原始类型
3b. "${var}" 嵌入字符串 → 字符串插值
4. 其他 → 原样返回
注意事项:
- 步骤引用只能引用已执行步骤的输出,不能向前引用
- 步骤 ID 中的连字符
-在引用中需要保留($load-roads,不能写成$load_roads) $step-id.attr中.只分割第一个,因此$step-id.stats.feature_count会尝试访问 stats 中的stats.feature_count键(通常不存在),正确写法是$step-id.feature_count(直接访问 stats 键)
5.4 在 when 条件中使用引用
when 表达式也支持步骤引用和变量替换:
steps:
- id: check-issues
use: qc.geometry_validity
params:
input: "$load-data"
auto_fix: false
# 条件1:基于步骤 stats 属性
- id: fix-issues
use: qc.geometry_validity
params:
input: "$load-data"
auto_fix: true
when: "$check-issues.issues_count > 0"
# 条件2:基于变量
- id: simplify
use: vector.simplify
params:
input: "$fix-issues"
tolerance: 10
when: "${enable_simplify} == true"
# 条件3:复合条件
- id: strict-fix
use: qc.geometry_validity
params:
input: "$load-data"
auto_fix: true
severity: "error"
when: "$check-issues.issues_count > 10 and ${strict_mode} == true"
5.5 在 outputs 中使用引用
outputs 声明支持完整的引用语法:
outputs:
final_result: "$save-result" # 输出文件路径
feature_count: "$buffer.feature_count" # 缓冲区要素数
total_area: "$buffer.total_area" # 缓冲区总面积
crs: "$reproject.crs" # 最终坐标系
qc_issues: "$check-geo.issues_count" # 质检问题数量
这些值出现在 JSON 报告的 outputs 节中,可供 AI 或下游系统提取。
5.6 嵌套参数中的引用
对于接受字典或列表类型参数的步骤,引用也可以出现在嵌套结构中:
# 假设某步骤接受字典参数
params:
config:
input: "$load-data" # 嵌套字典中的引用
crs: "${output_crs}"
field_list:
- "$load-data.columns" # 列表中的引用(按实际步骤支持情况)
5.7 常见引用错误
错误 1:引用未执行的步骤
steps:
- id: buffer
use: vector.buffer
params:
input: "$load-data" # ❌ load-data 在 buffer 之后,尚未执行
- id: load-data
use: io.read_vector
params: { path: "data.shp" }
错误 2:引用不存在的属性
- id: process
use: vector.buffer
params:
distance: "$load-data.record_count" # ❌ io.read_vector 没有 record_count 属性
# ✅ 应改为 feature_count
错误 3:ID 拼写不一致
steps:
- id: load-roads # ID 使用连字符
- id: buffer
params:
input: "$load_roads" # ❌ 使用了下划线,与 ID 不符
input: "$load-roads" # ✅ 正确
5.8 本章小结
本章深入讲解了 GeoPipeAgent 的两种核心数据传递机制:
- 变量替换
${var}:引用variables中的值,整个值时保留类型,嵌入字符串时做字符串插值 - 步骤引用
$step-id:$step-id是$step-id.output的简写,.attr可访问 stats/metadata 键 - 类型保留:单一
${var}引用保留原始 Python 类型,确保步骤参数类型正确 when条件:支持完整的引用语法,通过 AST 白名单安全求值StepResult结构:理解 output/stats/metadata/issues 各字段是正确使用引用的基础
下一章将讲解条件执行、自动重试和错误处理策略的详细用法。