修改问题:PS C:\Users\Administrator\Desktop\project> .\verify_event_center.ps1
=== 事件中心验证 ===
✅ 核心模块导入成功
SUCCESS
�����¼�����: 15
测试输出:
=== 验证完成 ===其它问题:::警告: 此模块应作为库导入,而非直接运行
=== EventCenter标准化测试 ===
Traceback (most recent call last):
File "C:\Users\Administrator\Desktop\project\core\event_center.py", line 300, in <module>
event_center.subscribe(EventType.TEST_EVENT, test_handler)
File "C:\Users\Administrator\Desktop\project\core\event_center.py", line 139, in subscribe
raise TypeError("event_type 必须是字符串或EventType枚举")
TypeError: event_type 必须是字符串或EventType枚举
进程已结束,退出代码为 1代码#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
事件中心模块 (最终优化版)
"""
import os
import sys
from pathlib import Path
# 关键修复1:更可靠的路径处理
def _init_paths():
"""更健壮的路径初始化"""
try:
# 直接定位项目根目录(假设core是子目录)
current_dir = Path(__file__).parent
root_dir = current_dir.parent if current_dir.name == "core" else current_dir
# 标准化路径处理
if str(root_dir) not in sys.path:
sys.path.insert(0, str(root_dir))
# 调试信息
if __debug__:
print(f"[DEBUG] 最终项目根目录: {root_dir}")
print(f"[DEBUG] 有效Python路径:")
for p in sys.path:
if "project" in p or "python" in p:
print(f" - {p}")
except Exception as e:
print(f"[CRITICAL] 路径初始化失败: {e}")
raise
import logging
import threading
import uuid
import time
from enum import Enum, auto
from typing import Dict, List, Callable, Optional, Any, Set, Tuple, DefaultDict, Union
from collections import defaultdict
from dataclasses import dataclass, field
from concurrent.futures import ThreadPoolExecutor
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
# 解决导入问题的关键修改:确保模块作为独立实体导入
if __name__ == "__main__":
print("警告: 此模块应作为库导入,而非直接运行")
from enum import Enum, auto
class EventType(Enum):
"""完整事件类型枚举"""
# 系统事件
SYSTEM_STARTUP = auto() # 系统启动
SYSTEM_SHUTDOWN = auto() # 系统关闭
MODULE_READY = auto() # 模块就绪(替换原来的HEARTBEAT)
ERROR = auto() # 错误事件(确保存在)
# 业务事件(对应5个核心模块)
INPUT_ANALYSIS_START = auto()
INPUT_ANALYSIS_END = auto()
COMBINATION_ANALYSIS_START = auto()
COMBINATION_ANALYSIS_END = auto()
FOLLOW_ANALYSIS_START = auto()
FOLLOW_ANALYSIS_UPDATE = auto()
TREND_ANALYSIS_REQUEST = auto()
TREND_ANALYSIS_REPORT = auto()
NUMBER_GENERATION_START = auto()
NUMBER_GENERATION_FINISH = auto()
# 测试事件
TEST_EVENT = auto() # 专门用于测试的事件类型
@dataclass
class Event:
"""事件数据类(优化验证逻辑)"""
type: Union[str, EventType]
source: str
event_id: str = field(default_factory=lambda: str(uuid.uuid4()))
target: Optional[str] = None
data: Optional[Dict[str, Any]] = field(default_factory=dict)
token: Optional[str] = None
timestamp: float = field(default_factory=time.time)
def __post_init__(self):
"""数据验证方法(优化验证逻辑)"""
self.type = self.type.value if isinstance(self.type, EventType) else self.type
if not isinstance(self.type, str) or not self.type:
raise ValueError("type 必须是非空字符串或EventType枚举")
if not isinstance(self.source, str) or not self.source:
raise ValueError("source 必须是非空字符串")
if self.target is not None and not isinstance(self.target, str):
raise ValueError("target 必须是字符串或None")
if not isinstance(self.data, dict):
raise ValueError("data 必须是字典")
class EventCenter:
"""线程安全的高性能事件中心单例"""
_instance = None
_lock = threading.Lock()
_executor = ThreadPoolExecutor(max_workers=10, thread_name_prefix="EventWorker")
def __new__(cls):
with cls._lock:
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance.__initialized = False
return cls._instance
def __init__(self):
if getattr(self, '__initialized', False):
return
self.__initialized = True
self._lock = threading.RLock()
self._subscribers: DefaultDict[str, List[Tuple[Callable[[Event], None], Optional[str]]]] = defaultdict(list)
self._event_history: Dict[str, Event] = {}
self._pending_acks: Set[str] = set()
self._ack_timeout = 5.0
self._event_counter = 0
self._failed_events = 0
logger.info("EventCenter 初始化完成 (线程安全单例)")
def subscribe(self, event_type: Union[str, EventType], handler: Callable[[Event], None],
token: Optional[str] = None) -> None:
"""订阅事件(支持EventType枚举和字符串)"""
event_type_str = event_type.value if isinstance(event_type, EventType) else event_type
if not isinstance(event_type_str, str):
raise TypeError("event_type 必须是字符串或EventType枚举")
if not callable(handler):
raise ValueError("handler 必须是可调用对象")
with self._lock:
self._subscribers[event_type_str].append((handler, token))
logger.debug("已订阅 %s [token=%s]", event_type_str, token)
def publish(self, event: Event, require_ack: bool = False, async_handle: bool = True) -> bool:
"""发布事件(优化性能和处理逻辑)"""
if not isinstance(event, Event):
raise TypeError("需要 Event 实例")
try:
event.__post_init__()
except ValueError as e:
logger.error("事件验证失败: %s", str(e))
self._failed_events += 1
return False
with self._lock:
if event.event_id in self._event_history:
logger.warning("重复事件 %s", event.event_id[:8])
return False
self._event_history[event.event_id] = event
self._event_counter += 1
if require_ack:
self._pending_acks.add(event.event_id)
logger.info("发布 %s 事件 %s (总事件数: %d)",
event.type, event.event_id[:8], self._event_counter)
handlers = self._get_matching_handlers(event)
if async_handle:
self._executor.submit(self._dispatch_event, event, handlers, require_ack)
else:
self._dispatch_event(event, handlers, require_ack)
return True
def _get_matching_handlers(self, event: Event) -> List[Callable[[Event], None]]:
"""获取匹配的事件处理器"""
with self._lock:
return [h for h, t in self._subscribers.get(event.type, [])
if t is None or t == event.token]
def _dispatch_event(self, event: Event, handlers: List[Callable[[Event], None]],
require_ack: bool) -> None:
"""分发事件(优化错误处理)"""
if not handlers:
logger.debug("事件 %s 无订阅处理器", event.event_id[:8])
return
for handler in handlers:
try:
start_time = time.perf_counter()
handler(event)
elapsed = (time.perf_counter() - start_time) * 1000
logger.debug("事件 %s 处理完成 [%s] (耗时 %.2fms)",
event.event_id[:8], handler.__name__, elapsed)
except Exception as e:
logger.exception("处理器 %s 失败: %s", handler.__name__, str(e))
self._publish_error(
source="event_center",
target=event.source,
error=e,
context=f"处理 {event.type} 时出错"
)
if require_ack and event.target:
self._wait_for_ack(event)
def _wait_for_ack(self, event: Event) -> None:
"""等待ACK(优化超时处理)"""
start = time.time()
while time.time() - start < self._ack_timeout:
with self._lock:
if event.event_id not in self._pending_acks:
logger.debug("收到 %s 的ACK", event.event_id[:8])
return
time.sleep(0.05) # 更短的等待间隔
logger.warning("事件 %s 等待ACK超时 (目标: %s)", event.event_id[:8], event.target)
self._publish_error(
source="event_center",
target=event.source,
error=TimeoutError(f"ACK超时 ({self._ack_timeout}s)"),
context=f"等待 {event.target} 确认超时"
)
def acknowledge(self, event_id: str) -> None:
"""确认事件处理完成(添加锁范围优化)"""
with self._lock:
if event_id in self._pending_acks:
self._pending_acks.remove(event_id)
logger.info("收到 %s 的ACK", event_id[:8])
else:
logger.warning("无效的ACK: %s (未找到或已处理)", event_id[:8])
def _publish_error(self, source: str, target: str, error: Exception,
context: str = "") -> None:
"""发布错误事件(优化错误信息结构)"""
error_event = Event(
type=EventType.ERROR,
source=source,
target=target,
data={
"error": str(error),
"type": type(error).__name__,
"context": context,
"stack_trace": logging.getTraceback()
}
)
self.publish(error_event)
def get_stats(self) -> Dict[str, int]:
"""获取事件中心统计信息(添加更多指标)"""
with self._lock:
return {
"total_events": self._event_counter,
"failed_events": self._failed_events,
"pending_acks": len(self._pending_acks),
"subscriber_types": len(self._subscribers),
"active_subscriptions": sum(len(h) for h in self._subscribers.values()),
"history_size": len(self._event_history)
}
def clear_subscriptions(self, event_type: Optional[Union[str, EventType]] = None) -> None:
"""清除订阅(支持按类型清除)"""
with self._lock:
if event_type is None:
self._subscribers.clear()
logger.info("清除所有订阅")
else:
event_type_str = event_type.value if isinstance(event_type, EventType) else event_type
if event_type_str in self._subscribers:
del self._subscribers[event_type_str]
logger.info("清除 %s 类型的所有订阅", event_type_str)
# 单例实例
event_center = EventCenter()
# 导出接口
__all__ = ['EventCenter', 'Event', 'EventType', 'event_center']
if __name__ == "__main__":
# 模块自测试代码
print("=== EventCenter标准化测试 ===")
# 测试处理器
def test_handler(event):
print(f"处理标准化测试事件: {event.type} (ID: {event.event_id[:8]})")
print(f"事件数据: {event.data}")
# 使用标准测试事件类型
event_center.subscribe(EventType.TEST_EVENT, test_handler)
# 创建标准测试事件
test_event = Event(
type=EventType.TEST_EVENT,
source="self_test",
data={
"message": "标准化测试事件",
"timestamp": time.time()
}
)
print("发布标准化测试事件...")
event_center.publish(test_event)
# 等待异步处理完成
time.sleep(0.5)
print("自测试完成,退出码: 0")
最新发布