日志
通过 master.logs 访问日志视图,或通过 LogManager.instance().default_view 全局访问。
运行日志由 SDK 各模块写入日志视图(只读列表);DLL 原生日志经 set_log_callback 回调推送给调用方。两者通道独立。
快速开始
from darra_ethercat import EtherCATMaster, LogCategory
# 绑定到控制台输出
master.logs.on_updated = lambda: print(master.logs[-1]) if master.logs.count > 0 else None
# 只看错误和警告
master.logs.set_filter(LogCategory.ERROR, LogCategory.WARNING)
# 启用调试日志(默认关闭)
EtherCATMaster.set_debug_logging(True)
日志类别
from enum import IntEnum
class LogCategory(IntEnum):
ERROR = 0 # 系统错误和异常
WARNING = 1 # 潜在问题
MESSAGE = 2 # 一般信息(状态切换等)
MAILBOX = 3 # CoE/SoE/FoE/EoE 邮箱通信(默认关闭)
PDO = 4 # PDO 数据变化日志(默认关闭)
DEBUG = 5 # 详细调试信息(默认关闭)
LOCAL = 6 # 控制台输出捕获
属性
| 类别 | 属性/方法 | 类型 | 读写 | 说明 |
|---|---|---|---|---|
| 视图 | master.logs | LogView | 只读 | 实时日志视图(等价 LogManager.instance().default_view) |
| on_updated | Optional[Callable[[], None]] | 读写 | 数据变化回调(无参函数),新增/清空/过滤器变化时触发 | |
| count | int | 只读 | 过滤后的日志条数 | |
| retain | bool | 读写 | 是否保留所有日志(默认 False) | |
set_filter(*categories) | None | 只写 | 设置类别过滤器,只显示指定类别 | |
| get_all() | List[LogEntry] | 只读 | 获取所有日志条目(无视过滤器) | |
| logs[i] / 迭代 | LogEntry | 只读 | 按索引取 / 遍历(均为过滤后视图) | |
| 回调 | master.set_log_callback(callback) | None | 只写 | 注册 DLL 原生日志回调 (category, message),传 None 清除 |
| master.set_crash_callback(callback) | None | 只写 | 注册崩溃通知回调 (severity, message),传 None 清除 |
master.logs
@property
def logs(self) -> LogView
实时日志视图(只读列表)。
LogEntry 数据类:
@dataclass
class LogEntry:
timestamp: datetime # 日志时间戳
category: LogCategory # 日志类别
message: str # 日志消息内容
on_updated
master.logs.on_updated = callback # callback() 无参,返回 None
日志数据变化时触发(新增/清空/过滤器变化)。
日志列表上限 10000 条,超出时自动移除最旧的 2000 条。
保留策略: master.logs.retain 默认 False——LogManager.instance().begin_operation() 进入首层操作时自动清空旧日志,只保留当前操作的日志;设 retain = True 则累积保留,不在操作边界清空。操作边界用 begin_operation() / end_operation() 标记。
PDO 日志只在 PDO 数据发生变化时输出,不会每个周期都产生日志。适合调试 PDO 映射问题。
过滤
set_filter()
def set_filter(self, *categories: LogCategory) -> None
设置过滤器,只显示指定类别的日志。
示例:
# 只看错误和警告
master.logs.set_filter(LogCategory.ERROR, LogCategory.WARNING)
# 切换为只看邮箱通信
master.logs.set_filter(LogCategory.MAILBOX)
get_all()
def get_all(self) -> List[LogEntry]
获取所有日志条目(无视过滤器)。
日志回调
set_log_callback()
def set_log_callback(self, callback: Optional[Callable[[int, str], None]]) -> None
注册 DLL 原生日志回调(进程级)。回调参数 (category, message)——category 为 LogCategory 取值(int),message 为日志文本。多 master 互不覆盖:重复调用只替换本实例上次注册的回调,传 None 清除。
set_crash_callback()
def set_crash_callback(self, callback: Optional[Callable[[int, str], None]]) -> None
注册崩溃通知回调(进程级)。回调参数 (severity, message),传 None 清除本实例的注册。
日志开关
Mailbox、PDO、Debug 三类日志默认关闭,需要时手动启用。
EtherCATMaster.set_pdo_logging(True)
EtherCATMaster.set_mailbox_logging(True)
EtherCATMaster.set_debug_logging(True)
日志开关详解
set_pdo_logging()
EtherCATMaster.set_pdo_logging(enable: bool) -> None
启用 PDO 日志。仅在 PDO 数据变化时输出,影响实时性能,慎用。
set_mailbox_logging()
EtherCATMaster.set_mailbox_logging(enable: bool) -> None
启用邮箱日志(CoE/SoE/FoE/EoE 邮箱通信日志)。
set_debug_logging()
EtherCATMaster.set_debug_logging(enable: bool) -> None
启用调试日志(详细调试信息)。
完整示例
from darra_ethercat import EtherCATMaster, LogCategory
# 1. 绑定控制台输出
master.logs.on_updated = lambda: print(master.logs[-1]) if master.logs.count > 0 else None
# 2. 启用调试日志
EtherCATMaster.set_debug_logging(True)
EtherCATMaster.set_mailbox_logging(True)
# 3. 过滤日志
master.logs.set_filter(LogCategory.ERROR, LogCategory.DEBUG)
# 4. 导出所有日志(无视过滤器)
all_logs = master.logs.get_all()
with open("debug.log", "w", encoding="utf-8") as f:
for entry in all_logs:
f.write(f"{entry}\n")
on_updated 在非 UI 线程触发,更新 UI 时需要同步:
# tkinter
master.logs.on_updated = lambda: root.after(0, lambda: listbox.insert("end", str(master.logs[-1])))
# PyQt
from PyQt5.QtCore import QMetaObject, Qt, Q_ARG
master.logs.on_updated = lambda: QMetaObject.invokeMethod(
widget, "append_log", Qt.QueuedConnection, Q_ARG(str, str(master.logs[-1])))