Skip to content

Skills 错误处理与容错

一个只能在理想情况下运行的 Skill 是脆弱的。

健壮的 Skill 需要预见常见错误,给出清晰的反馈,并尽可能自动恢复。


错误处理的三个层次

层次发生位置处理方式
输入验证错误执行前检查输入,若不合法直接拒绝并说明原因
运行时错误脚本执行中捕获异常,输出结构化错误信息
结果异常执行完成后验证输出是否符合预期,若不符合触发补救流程

在 SKILL.md 中定义错误处理策略

SKILL.md 中应当包含一个明确的错误处理章节,告诉 Claude 遇到问题时该怎么做。

实例

bash

## 错误处理

### 输入问题

- 文件不存在:告知用户文件路径有误,请重新上传

- 文件格式不支持:列出支持的格式(pdf、docx、txt),请用户转换后重试

- 文件为空:告知文件内容为空,无法处理

### 执行问题

- 脚本运行失败:将完整错误信息展示给用户,不要隐藏

- 依赖未安装:先尝试自动安装(pip install),若失败则告知用户手动安装

- 超时:若超过 60 秒未完成,输出当前进度并询问用户是否继续等待

### 结果问题

- 输出文件为空:重新检查处理逻辑,向用户说明可能原因

- 输出格式不符合预期:展示实际输出,询问用户是否满意

脚本中的标准错误处理模式

Python 脚本应使用 try-except 结构,并统一返回包含 status 字段的 JSON。

实例

python

# 文件路径:scripts/error_handling_demo.py

import json

import sys

import os

class SkillError(Exception):

    """Skill 自定义异常基类"""

    def __init__(self, message: str, code: str):

        self.message = message

        self.code    = code     # 错误码,便于程序判断错误类型

        super().__init__(message)

class InputError(SkillError):

    """输入验证错误"""

    pass

class ProcessError(SkillError):

    """处理过程错误"""

    pass

def validate_input(file_path: str) -> None:

    """验证输入,出错时抛出 InputError"""

    if not file_path:

        raise InputError("未提供文件路径", "MISSING_FILE")

    if not os.path.exists(file_path):

        raise InputError(f"文件不存在:{file_path}", "FILE_NOT_FOUND")

    if os.path.getsize(file_path) == 0:

        raise InputError(f"文件内容为空:{file_path}", "EMPTY_FILE")

def process(file_path: str) -> dict:

    """主处理逻辑"""

    try:

        validate_input(file_path)

        with open(file_path, "r", encoding="utf-8") as f:

            content = f.read()

        # 实际处理逻辑(此处简化为行数统计)

        lines = content.split("\n")

        return {

            "status": "success",

            "data": {

                "file":  file_path,

                "lines": len(lines),

                "chars": len(content)

            }

        }

    except InputError as e:

        # 输入错误:用户可以修正后重试

        return {

            "status":  "input_error",

            "code":    e.code,

            "message": e.message,

            "hint":    "请检查文件路径是否正确,文件是否存在且非空"

        }

    except UnicodeDecodeError:

        # 编码错误:给出具体的修复建议

        return {

            "status":  "process_error",

            "code":    "ENCODING_ERROR",

            "message": "文件编码不是 UTF-8,无法读取",

            "hint":    "请将文件另存为 UTF-8 编码后重试"

        }

    except Exception as e:

        # 未预期的错误:完整记录,便于调试

        return {

            "status":  "unexpected_error",

            "code":    "UNKNOWN",

            "message": str(e),

            "hint":    "请将上述错误信息反馈给开发者"

        }

if __name__ == "__main__":

    file_path = sys.argv[1] if len(sys.argv) > 1 else ""

    result    = process(file_path)

    print(json.dumps(result, ensure_ascii=False, indent=2))
bash
# 文件存在时的成功输出:
{
  "status": "success",
  "data": {
    "file": "/mnt/user-data/uploads/runoob.txt",
    "lines": 128,
    "chars": 5432
  }
}

# 文件不存在时的错误输出:
{
  "status": "input_error",
  "code": "FILE_NOT_FOUND",
  "message": "文件不存在:/mnt/user-data/uploads/missing.txt",
  "hint": "请检查文件路径是否正确,文件是否存在且非空"
}

依赖自动安装的容错模式

当脚本依赖的 Python 包未安装时,可以在脚本中自动尝试安装。

实例

python

# 文件路径:scripts/auto_install_demo.py

import subprocess

import sys

def ensure_package(package_name: str, import_name: str = None) -> bool:

    """

    确保 Python 包已安装,若未安装则自动安装

    参数:

        package_name: pip 安装时使用的包名(如 "python-docx")

        import_name:  import 时使用的名称(如 "docx"),默认与 package_name 相同

    """

    import_name = import_name or package_name

    try:

        __import__(import_name)

        return True  # 已安装

    except ImportError:

        print(f"正在安装依赖:{package_name}...")

        result = subprocess.run(

            [sys.executable, "-m", "pip", "install", package_name,

             "--break-system-packages", "--quiet"],

            capture_output=True, text=True

        )

        if result.returncode == 0:

            print(f"安装成功:{package_name}")

            return True

        else:

            print(f"安装失败:{package_name}")

            print(result.stderr)

            return False

# 使用示例:在脚本开头确保所有依赖已就绪

if not ensure_package("pandas"):

    sys.exit(1)

if not ensure_package("openpyxl"):

    sys.exit(1)

# 依赖就绪后,正常 import

import pandas as pd

print("所有依赖已就绪,开始执行...")

自动安装只适用于开发和轻量级场景。在生产环境的 Skill 中,应将依赖写入文档,由用户预先安装,而不是在运行时自动安装。


错误信息的书写规范

好的错误信息能帮助用户快速定位问题,差的错误信息只会让人困惑。

维度差的写法好的写法
描述问题"出错了""文件 report.csv 不存在于上传目录"
说明原因(无)"可能是文件名拼写有误,或文件尚未上传"
提供行动(无)"请重新上传文件,或检查文件名是否正确"

实例

bash

# 差的错误信息

raise Exception("Error")

# 好的错误信息

raise InputError(

    "文件 runoob_data.csv 未在上传目录中找到。"

    "可能原因:文件名拼写有误,或文件尚未上传。"

    "请重新上传文件后再试。",

    code="FILE_NOT_FOUND"

)

AI 思考中...

Skills 输入/输出规范设计

Skills 上下文与状态管理

基于 VitePress 构建,部署于 GitHub Pages