17.3 添加脚本和可执行代码
第 17 章 · 开发一个技能 · 第5部分:技能 Skills
概述#
当SKILL.md中的指令描述不足以完成复杂任务时,你可以通过添加可执行脚本和代码来增强Skill的功能。这些脚本可以处理计算密集型任务、外部API调用、文件处理等操作,让Skill变得更加智能和实用。
脚本是Skill的"执行引擎",让Claude能够从"指导者"转变为"实干家"。
何时需要添加脚本#
1. 计算密集型任务#
当任务需要复杂的数学计算、数据处理或算法执行时:
适用场景:
- 大数据分析和统计计算
- 图像处理和格式转换
- 加密解密操作
- 机器学习模型推理
示例:
markdown复制# 在SKILL.md中引用脚本 ## 数据分析 对于复杂的数据分析,使用内置脚本: ```bash python scripts/analyze_data.py --input data.csv --output report.json ```
2. 外部系统集成#
当需要与外部API、数据库或服务交互时:
适用场景:
- 调用REST API获取数据
- 连接数据库执行查询
- 与云服务集成(如AWS、Google Cloud)
- 调用命令行工具
示例:
markdown复制## API集成 调用外部服务获取最新数据: ```bash python scripts/fetch_api_data.py --endpoint https://api.example.com/data ```
3. 文件和数据处理#
当需要复杂的文件操作或数据转换时:
适用场景:
- 批量文件处理
- 数据格式转换(JSON↔XML↔CSV)
- 压缩解压操作
- 文件校验和验证
4. 自动化工作流#
当任务涉及多个步骤的自动化执行时:
适用场景:
- CI/CD流水线
- 批量数据迁移
- 系统部署和配置
- 定期备份任务
脚本存放规范#
目录结构#
遵循标准化的目录结构,便于管理和维护:
bash复制my-skill/ ├── SKILL.md ├── scripts/ │ ├── analyze_data.py # 数据分析脚本 │ ├── fetch_api.py # API调用脚本 │ ├── process_files.py # 文件处理脚本 │ └── utils/ │ ├── helpers.py # 辅助函数 │ └── validators.py # 验证函数 ├── assets/ │ └── templates/ │ └── report_template.json └── tests/ ├── test_scripts.py └── fixtures/ └── sample_data.json
命名规范#
使用清晰、一致的命名约定:
- 文件名:使用小写字母和下划线,如
data_processor.py - 函数名:使用小写字母和下划线,如
process_data() - 类名:使用大驼峰命名,如
DataProcessor - 常量:使用大写字母和下划线,如
MAX_RETRY_COUNT
文件权限设置#
确保脚本具有正确的执行权限:
bash复制# 设置Python脚本为可执行chmod +x scripts/data_processor.py # 设置Shell脚本为可执行chmod +x scripts/deploy.sh
Claude调用脚本的机制#
1. 指令中的脚本引用#
在SKILL.md中明确告诉Claude如何调用脚本:
markdown复制## 数据处理步骤 1. **验证输入数据** ```bash python scripts/validate_input.py --file input.csv ``` 2. **执行数据转换** ```bash python scripts/transform_data.py --input input.csv --output output.json ``` 3. **生成结果报告** ```bash python scripts/generate_report.py --data output.json --template report_template.md ```
2. 参数传递机制#
Claude通过命令行参数向脚本传递信息:
markdown复制## 用户自定义处理 当用户指定特定参数时: ```bash python scripts/custom_process.py --user_input "{{user_input}}" --options "{{options}}" ```
Claude会自动替换 {{user_input}} 和 {{options}} 为实际值。
3. 错误处理和重试#
指导Claude如何处理脚本执行失败:
markdown复制## 错误处理 如果脚本执行失败: 1. 检查错误信息:`echo "Error details: {{error_message}}"` 2. 重试操作:`python scripts/retry_operation.py --attempt 2` 3. 回退方案:使用备用脚本 `python scripts/fallback.py`
脚本开发最佳实践#
1. 输入验证#
始终验证输入参数的有效性:
python复制# scripts/data_processor.pyimport sys import argparse defvalidate_input(file_path, output_format):"""验证输入参数"""ifnot file_path ornot os.path.exists(file_path):print(f"Error: Input file '{file_path}' not found") sys.exit(1) valid_formats =['json','xml','csv']if output_format notin valid_formats:print(f"Error: Invalid output format '{output_format}'. Valid options: {valid_formats}") sys.exit(1) defmain(): parser = argparse.ArgumentParser(description='Process data files') parser.add_argument('--input', required=True,help='Input file path') parser.add_argument('--output', required=True,help='Output file path') parser.add_argument('--format', default='json', choices=['json','xml','csv'],help='Output format') args = parser.parse_args() # 验证输入 validate_input(args.input, args.format) # 处理数据 process_data(args.input, args.output, args.format)print(f"Processing complete. Output saved to {args.output}") if __name__ =='__main__': main()
2. 输出格式标准化#
使用一致的输出格式,便于Claude解析:
python复制# scripts/api_fetcher.pyimport json import sys deffetch_data(api_url, timeout=30):"""获取API数据"""try:# API调用逻辑 result ={"success":True,"data": fetched_data,"timestamp": get_timestamp()}print(json.dumps(result, indent=2))except Exception as e: error_result ={"success":False,"error":str(e),"timestamp": get_timestamp()}print(json.dumps(error_result, indent=2)) sys.exit(1) defmain():# 参数解析和调用逻辑pass if __name__ =='__main__': main()
3. 日志记录#
添加适当的日志输出,帮助调试:
python复制# scripts/file_processor.pyimport logging import sys # 配置日志logging.basicConfig( level=logging.INFO,format='%(asctime)s - %(levelname)s - %(message)s') defprocess_files(file_list):"""处理文件列表""" logger = logging.getLogger(__name__) for file_path in file_list:try: logger.info(f"Processing file: {file_path}")# 处理逻辑 logger.info(f"Successfully processed: {file_path}")except Exception as e: logger.error(f"Failed to process {file_path}: {e}")# 决定是否继续处理其他文件 defmain():# 主逻辑pass if __name__ =='__main__': main()
参数传递和返回值处理#
1. 参数传递方式#
Claude可以通过多种方式向脚本传递参数:
命令行参数
markdown复制## 数据分析 ```bash python scripts/analyze.py --file "{{file_path}}" --method "{{analysis_method}}" --output "{{output_path}}" ```
环境变量
markdown复制## 配置加载 ```bash export API_KEY="{{api_key}}" export DEBUG="{{debug_mode}}" python scripts/process_data.py ```
标准输入
markdown复制## 批量处理 ```bash echo "{{data_list}}" | python scripts/batch_processor.py ```
2. 返回值处理#
脚本应该返回结构化的结果,便于Claude理解:
python复制# scripts/result_formatter.pyimport json import sys defformat_result(success, data=None, error=None, metadata=None):"""格式化返回值""" result ={"success": success,"timestamp": get_current_timestamp(),"metadata": metadata or{}} if success: result["data"]= data else: result["error"]= error return result defmain():try:# 处理逻辑 processed_data = perform_processing() result = format_result(True, data=processed_data, metadata={"records_processed":len(processed_data)})except Exception as e: result = format_result(False, error=str(e)) # 输出JSON结果print(json.dumps(result, indent=2)) if __name__ =='__main__': main()
调试脚本执行问题#
1. 常见问题诊断#
脚本找不到
markdown复制## 诊断步骤 1. 确认脚本路径:`ls -la scripts/my_script.py` 2. 检查文件权限:`ls -l scripts/my_script.py` 3. 验证Python路径:`which python` 4. 测试脚本执行:`python scripts/my_script.py --help`
参数传递错误
markdown复制## 参数验证 检查传递的参数: ```bash echo "Received parameters: {{all_parameters}}" python scripts/validate_params.py --params "{{all_parameters}}" ```
依赖缺失
markdown复制## 依赖检查 ```bash python -c "import required_module; print('Module available')" pip install missing-dependency ```
2. 调试技巧#
添加调试输出
markdown复制## 调试模式 启用详细输出: ```bash export DEBUG=1 python scripts/debug_script.py --input "{{input_data}}" ```
逐步执行
markdown复制## 分步调试 1. 验证输入:`python scripts/validate.py --input "{{input}}"` 2. 执行处理:`python scripts/process.py --validated-input validated.json` 3. 生成输出:`python scripts/output.py --processed-data processed.json`
日志分析
markdown复制## 日志检查 查看执行日志: ```bash tail -f /tmp/skill_execution.log python scripts/analyze_logs.py --log-file /tmp/skill_execution.log ```
3. 错误恢复机制#
markdown复制## 错误处理流程 如果脚本执行失败: ### 临时文件清理 ```bash rm -f /tmp/temp_*.tmp ``` ### 状态重置 ```bash python scripts/reset_state.py --clean-workspace ``` ### 备用方案 ```bash python scripts/fallback_processor.py --input "{{original_input}}" ``` ### 用户通知 ``` 执行过程中遇到错误:{{error_message}} 已尝试自动恢复,请检查结果或重试操作。 ```
实际案例:数据分析Skill#
SKILL.md配置#
markdown复制--- name: data-analyzer description: 执行复杂数据分析任务,包括统计计算、可视化和报告生成 --- # 数据分析助手 ## 基本分析 ```bash python scripts/basic_stats.py --data "{{data_file}}" --output "{{stats_file}}" ``` ## 高级分析 ```bash python scripts/advanced_analysis.py --data "{{data_file}}" --method "{{analysis_method}}" --visualize ``` ## 报告生成 ```bash python scripts/generate_report.py --stats "{{stats_file}}" --template report_template.md --output "{{report_file}}" ``` ## 故障排除 - 如果分析失败,检查数据格式:`python scripts/validate_data.py --file "{{data_file}}"` - 内存不足时,使用流式处理:`python scripts/stream_processor.py --input "{{data_file}}"`
脚本示例#
python复制# scripts/basic_stats.pyimport pandas as pd import json import sys defcalculate_basic_stats(data_file):"""计算基本统计信息"""try: df = pd.read_csv(data_file) stats ={"row_count":len(df),"column_count":len(df.columns),"columns":list(df.columns),"numeric_stats":{}} # 数值列统计 numeric_columns = df.select_dtypes(include=['number']).columns for col in numeric_columns: stats["numeric_stats"][col]={"mean":float(df[col].mean()),"median":float(df[col].median()),"std":float(df[col].std()),"min":float(df[col].min()),"max":float(df[col].max())} return stats except Exception as e:print(f"Error calculating stats: {e}",file=sys.stderr) sys.exit(1) defmain():import argparse parser = argparse.ArgumentParser(description='Calculate basic statistics') parser.add_argument('--data', required=True,help='Input data file') parser.add_argument('--output', required=True,help='Output stats file') args = parser.parse_args() stats = calculate_basic_stats(args.data) withopen(args.output,'w')as f: json.dump(stats, f, indent=2) print(f"Statistics saved to {args.output}") if __name__ =='__main__': main()
通过精心设计的脚本,你可以让Skill处理几乎任何类型的任务。记住,脚本应该是可靠的、文档化的,并且能够优雅地处理错误情况。这样,Claude就可以专注于决策和指导,而将具体的执行工作交给脚本处理。