px普贤教程PuXian
普贤教程 › 参考手册

错误码速查

PuXian 的报错格式统一:先是类别,再是错误码与位置,最后是人话说明。看懂这一行,八成的调试就完成了。

报错长什么样

text
运行时错误: 错误 [R1002] 1:11: 无法相加: string + int
位置含义
运行时错误 / 语法错误发生在运行期还是编译期
R1002错误码
1:11行号:列号(从 1 开始)
无法相加: string + int具体原因

语法错误(E 系列)

码含义常见触发
E2001期望的记号不对漏冒号、缩进错、把保留字当变量名、把赋值写成表达式
text
2:9: 语法错误 E2001: 期望变量名,实际得到 from
25:18: 语法错误 E2001: 期望 ')',实际得到 if
5:44: 语法错误 E2001: 期望 '}',实际得到 =

三种典型:用了保留字 from;写了三元表达式(a if c else b);在 fn 里把赋值当表达式。

运行错误(R 系列)

码含义典型触发处理
R1001未定义变量拼错名字;import 没生效;跨目录 import检查拼写与 import 路径
R1002类型不匹配"x" + 1、int("abc")、join 参数写反转成同类型再运算
R1004unwrap 失败对 Err 调 unwrap()先判 is_err()
R1007类型没有该字段/方法xs.insert()、str.status查可用方法清单
R1008字典没有该键d["missing"]先 d.has(k)

内建函数内部失败

前缀含义
i_call_builtin内建函数执行失败,如 json_parse 遇到坏 JSON、写文件失败
i_builtin_ffi_call参数类型不匹配,如把 int 传给要字符串的 tz
it_dirname取路径目录时文件不存在(编译器内部)
text
运行时错误 [i_call_builtin 行372]: io: 写入文件失败 ../build/index.html
运行时错误 [i_builtin_ffi_call 行1284]: R1002: time_format 的 tz 需要字符串,实际是 int
运行时错误 [it_dirname 行161]: io: 读取文件失败 bench.px

按报错找原因:速查

报错八成是什么
未定义变量: 'xxx'函数名拼错;或 import 没写;或用了 keys(d) 这类不存在的内建
无法相加: string + int拼接前忘了 str()
无法将 'abc' 转为 int外部输入没校验就 int()
字典没有键直接读可能不存在的键
类型 list 没有方法 'insert'记成了 Python 的 API
期望变量名,实际得到 XXX用了保留字(from / in / type 之外的)
写入文件失败父目录不存在或无权限
段错误(Segmentation fault)函数名与内建同名导致递归(如 def env())

调试手段

  1. 打点:print("到这里 " + str(x))。解释轨里最直接。
  2. 缩小范围:把出错行前后各删一半,看错误消失在哪一步。
  3. 静态检查:px lint x.px 能在运行前抓到语法与部分语义问题。
  4. 看行列号:报错给的是精确位置,别只看行号忽略列号——同一行里 + 左边还是右边出错,结果完全不同。
  5. 日志走 stderr:在 Ma 的 px_routes 里,print 会污染响应体,调试输出必须写 /dev/stderr。

错误处理的正确姿势

场景做法
可预期的失败(文件不存在、参数不合法)返回 Ok / Err,调用方处理
不可能发生的内部错误让它崩,日志里留下行列号
外部数据先校验,再调用会终止进程的函数(int、json_parse)
接口入口包一层统一返回 400/500,别让子进程崩掉整个请求
px
# 入口处兜底:任何异常输入都变成 400,而不是 500
def guard(raw, fn):
    var p = json_parse_opt(raw)
    if p.is_err():
        return {"status": 400, "body": {"ok": false, "error": "请求体不是合法 JSON"}}
    return fn(p.ok())