当前位置: 首页 > news >正文

HoRain云--Skills 日志与调试进阶

🎬 HoRain 云小助手:个人主页

⛺️生活的理想,就是为了理想的生活!


⛳️ 推荐

前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!忍不住分享一下给大家。点击跳转到网站。

目录

⛳️ 推荐

用 logging 替代 print

实例

执行时间追踪

实例

结构化日志:输出 JSON 格式

实例

调试 SKILL.md 的指令执行

常见调试场景速查


入门调试靠 print,进阶调试靠系统性的日志机制。

本篇介绍如何为 Skill 脚本建立结构化日志,以及在复杂执行流程中定位问题的进阶技巧。


用 logging 替代 print

print 适合快速调试,但在正式 Skill 中应改用 Python 标准库的 logging 模块。

logging 的优势是可以控制输出级别——开发时输出 DEBUG 信息,生产时只输出 WARNING 以上。

实例

# 文件路径:scripts/logger_setup.py
import logging
import sys
from datetime import datetime

def get_logger(name: str, level: str = "INFO") -> logging.Logger:
"""
创建结构化日志记录器

参数:
name: 日志器名称,通常用模块名(__name__)
level: 日志级别,DEBUG / INFO / WARNING / ERROR
"""
logger = logging.getLogger(name)
logger.setLevel(getattr(logging, level.upper(), logging.INFO))

# 避免重复添加 handler
if logger.handlers:
return logger

# 控制台输出:人类可读格式
console = logging.StreamHandler(sys.stdout)
console.setFormatter(logging.Formatter(
"[%(asctime)s] [%(levelname)s] %(name)s - %(message)s",
datefmt="%H:%M:%S"
))
logger.addHandler(console)

# 文件输出:写入日志文件(可选)
log_file = f"/home/claude/skill_{datetime.now().strftime('%Y%m%d')}.log"
file_handler = logging.FileHandler(log_file, encoding="utf-8")
file_handler.setFormatter(logging.Formatter(
"%(asctime)s [%(levelname)s] %(name)s:%(lineno)d - %(message)s"
))
logger.addHandler(file_handler)

return logger

# 使用示例
if __name__ == "__main__":
log = get_logger(__name__, level="DEBUG")

log.debug("调试信息:文件路径 = /mnt/user-data/uploads/runoob.csv")
log.info("开始处理文件")
log.warning("文件大小超过 50MB,处理可能较慢")
log.error("文件读取失败:FileNotFoundError")

[10:23:01] [DEBUG] __main__ - 调试信息:文件路径 = /mnt/user-data/uploads/runoob.csv [10:23:01] [INFO] __main__ - 开始处理文件 [10:23:01] [WARNING] __main__ - 文件大小超过 50MB,处理可能较慢 [10:23:01] [ERROR] __main__ - 文件读取失败:FileNotFoundError

执行时间追踪

当 Skill 执行较慢时,需要找出耗时的瓶颈步骤。

实例

# 文件路径:scripts/timer.py
import time
import functools
import logging

log = logging.getLogger(__name__)

def timeit(func):
"""装饰器:自动记录函数执行时间"""
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
elapsed = time.perf_counter() - start
log.info(f"{func.__name__} 耗时 {elapsed:.3f} 秒")
return result
return wrapper

# 使用方式:在需要计时的函数上加 @timeit 装饰器
@timeit
def load_csv(file_path: str):
import pandas as pd
return pd.read_csv(file_path)

@timeit
def calculate_stats(df):
return df.describe()

# 也可以用上下文管理器手动计时
class Timer:
def __init__(self, label: str):
self.label = label
def __enter__(self):
self.start = time.perf_counter()
return self
def __exit__(self, *args):
elapsed = time.perf_counter() - self.start
log.info(f"{self.label} 耗时 {elapsed:.3f} 秒")

# 使用 Timer 上下文管理器
if __name__ == "__main__":
with Timer("读取并清洗数据"):
import pandas as pd
df = pd.read_csv("/mnt/user-data/uploads/runoob_data.csv")
df = df.dropna()

[10:23:05] [INFO] load_csv 耗时 0.342 秒 [10:23:05] [INFO] calculate_stats 耗时 0.018 秒 [10:23:05] [INFO] 读取并清洗数据 耗时 0.361 秒

结构化日志:输出 JSON 格式

当日志需要被程序解析(而非人工阅读)时,JSON 格式更合适。

实例

# 文件路径:scripts/json_logger.py
import json
import sys
from datetime import datetime

def log_event(level: str, event: str, **context):
"""
输出结构化 JSON 日志

参数:
level: 日志级别(info / warning / error)
event: 事件名称
context: 附加的上下文键值对
"""
entry = {
"timestamp": datetime.now().isoformat(),
"level": level,
"event": event,
**context
}
# 使用 stderr 输出日志,避免与脚本的正常输出混合
print(json.dumps(entry, ensure_ascii=False), file=sys.stderr)

# 使用示例
log_event("info", "file_loaded", file="/mnt/user-data/uploads/runoob.csv", rows=1024)
log_event("warning", "null_detected", column="score", count=12)
log_event("error", "parse_failed", reason="编码不是 UTF-8")

{"timestamp": "2026-05-18T10:23:05", "level": "info", "event": "file_loaded", "file": "/mnt/user-data/uploads/runoob.csv", "rows": 1024} {"timestamp": "2026-05-18T10:23:05", "level": "warning", "event": "null_detected", "column": "score", "count": 12} {"timestamp": "2026-05-18T10:23:05", "level": "error", "event": "parse_failed", "reason": "编码不是 UTF-8"}

调试 SKILL.md 的指令执行

当 Claude 没有按照 SKILL.md 的指令执行时,可以通过在 SKILL.md 中插入"检查点"来定位问题。

## 调试检查点(开发模式,发布前删除) 在执行每个步骤前,先以以下格式输出一行状态确认: `[STEP N] 开始:{步骤名称},输入:{关键参数}` 示例: `[STEP 1] 开始:读取文件,输入:/mnt/user-data/uploads/runoob.csv` `[STEP 2] 开始:数据清洗,输入:1024 行` 这样可以在出错时快速定位到哪个步骤失败。

调试检查点是临时的。调试完成后,务必从 SKILL.md 中删除这些指令,否则正式使用时用户会看到多余的调试输出。


常见调试场景速查

场景调试方法
Skill 未触发检查 description、使用复杂提示词测试、运行 run_loop.py 优化
脚本报 ImportError运行 pip install,检查包名与 import 名称是否匹配
文件路径报错先 ls /mnt/user-data/uploads/ 确认文件名
输出乱码在文件读取时显式指定 encoding="utf-8"
步骤执行顺序不对在 SKILL.md 中用编号列表明确步骤顺序
结果为空在脚本关键节点加 print,确认数据在哪一步变空

❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙

http://www.jsqmd.com/news/858777/

相关文章:

  • 如何快速掌握UESave:3个高效编辑游戏存档的秘诀
  • 7天职场内耗清零打卡计划
  • Midscene.js终极指南:用AI视觉驱动实现跨平台自动化
  • 2026年广东水上挖掘机租赁、河道清淤、滩涂开发一站式解决方案深度指南 - 年度推荐企业名录
  • 《Windows Sysinternals实战指南》VMMap 学习笔记(8.4):时间线与快照——如何证明它“越跑越吃内存”
  • 通过 Taotoken 用量看板追溯账单与分析各模型调用分布的实际案例
  • 3步打造你的私人游戏串流平台:Sunshine终极使用指南
  • Pitest架构深度解析:理解主进程与子进程的高效协作机制
  • Egg.js CNode社区API开发:5个RESTful API设计与实现的关键技巧
  • Wannakey终极指南:免费恢复WannaCry加密文件的专业内存密钥恢复工具
  • 在 OpenClaw 中配置 Taotoken 作为 OpenAI 兼容提供商详解
  • 如何快速掌握OBS背景移除插件:从零到专业的完整指南
  • 为OpenClaw工具快速写入Taotoken配置实现AI助手无缝切换
  • 2026年西安商业空间设计与高端私宅全案定制深度指南:刘红旺与张劲夫两大设计师实力对比 - 精选优质企业推荐官
  • fltk-rs高级特性揭秘:多线程、图像处理和OpenGL集成终极指南
  • 《VLA 系列》复现 π0.5 | 数据采集 | 模型微调 | DROID
  • G-Helper完整指南:华硕笔记本轻量控制神器的终极解决方案
  • 在Taotoken模型广场根据任务需求与预算快速选型实践
  • OpenAI Codex 安装指南
  • Obsidian加州海岸主题:如何用这款macOS风格主题让你的笔记效率翻倍?
  • 如何用markdownReader在3分钟内提升你的Markdown阅读体验300%?
  • 10分钟终极指南:使用Chronos时间序列预测模型快速上手
  • 从零开始玩转Switch游戏:Ryujinx模拟器终极指南
  • Super Productivity:终极时间盒管理工具,免费开源的任务追踪与时间管理解决方案
  • 实战指南:高效部署AI视频场景分割工具的完整方案
  • HEIF扩展功能开发:自定义图像属性和元数据的实现方法
  • Python爬虫实战:手把手教你如何采集灌区基础信息公开页!
  • 通过Taotoken CLI工具一键配置团队统一的AI助手开发环境
  • ComfyUI-Impact-Pack:如何通过模块化架构实现AI图像处理的性能突破
  • 2026年5月最新 浸没式浊度计选型对比 - 水质仪表品牌排行榜