
在 zope 5 的 python 脚本中捕获异常后,需在 `except` 块中主动将错误写入 zope 内置的 `error_log`(而非自定义文件或消息),同时继续执行 json 返回逻辑——推荐使用标准 `logging` 模块配合 zope 预配置的日志处理器实现。
Zope 5 默认已将 logging 模块与内置 error_log 对象深度集成:只要使用 logging.getLogger() 获取任意命名的 logger,并调用 .error() 或 .exception() 方法,Zope 就会自动将日志事件路由至 error_log(位于 ZMI 中的 /error_log),并保留完整的异常堆栈、时间戳、请求上下文等元信息——这正是你期望的“标准异常日志行为”。
关键在于:不要尝试直接调用 SiteErrorLog.raising()(它依赖实例上下文,在受限脚本中难以正确传参,且 Zope 5 已不鼓励该低层用法);而是采用标准、轻量、Zope 原生支持的 logging 接口。
✅ 正确做法:使用 logging.exception() 记录完整异常
修改你的脚本如下(无需外部方法、无需 allow_module 配置):
import json
from logging import getLogger
# 获取一个具名 logger(名称可自定义,如 'zope.jsonapi')
logger = getLogger("zope.jsonapi")
try:
context.my_zsql_method()
return json.dumps({"output": "success"})
except Exception as e:
# ✅ 关键:使用 .exception() 自动记录异常类型、消息和完整 traceback
logger.exception("JSON API call failed in my_zsql_method")
# 继续返回 JSON,不影响后续逻辑
return json.dumps({"output": "failure"})? logger.exception(msg) 是 logger.error(msg, exc_info=True) 的快捷方式,它会自动捕获当前异常上下文(sys.exc_info()),确保 error_log 中显示与未捕获异常完全一致的堆栈跟踪。
⚠️ 注意事项
- 无需额外配置:Zope 5 默认已将 logging 输出重定向至 error_log。只要 logger.level
- 避免 logger.error(str(e)):仅记录字符串会丢失堆栈,无法在 ZMI error_log 中展开查看详情。
- 命名 logger 的建议:使用语义化名称(如 "zope.jsonapi")便于后期在 error_log 界面按 Logger Name 过滤,也利于调试定位。
- 受限脚本兼容性:logging.getLogger() 在 Zope 的受限 Python 环境中完全可用,无权限问题,比操作 SiteErrorLog 类更安全可靠。
- 性能无负担:logging 是轻量级、惰性求值的,仅在触发时才格式化和分发日志。
✅ 验证效果
执行脚本触发异常后,访问 ZMI → /error_log → 查看最新条目,你将看到:
立即学习“Python免费学习笔记(深入)”;
- Logger Name: zope.jsonapi
- Time: 精确到毫秒的时间戳
- Level: ERROR
- Traceback: 完整可折叠的异常堆栈(含 my_zsql_method 调用链)
- Request URL, User, Client IP 等上下文信息(Zope 自动注入)
这正是 Zope 原生错误日志体验,且与你的 JSON 返回逻辑完全解耦。
总结:放弃对 SiteErrorLog.raising() 的复杂适配,拥抱 Python 标准 logging ——它简洁、健壮、Zope 原生支持,且一行代码即可精准复现默认异常日志行为。










