"""脚本执行器 - 安全执行Python脚本""" import sys import traceback from io import StringIO from typing import Any, Dict, Optional, Tuple from datetime import datetime from sqlalchemy.orm import Session from .script_sdk import ScriptSDK # 禁止导入的模块 FORBIDDEN_MODULES = { 'os', 'subprocess', 'shutil', 'pathlib', 'socket', 'ftplib', 'telnetlib', 'smtplib', 'pickle', 'shelve', 'marshal', 'ctypes', 'multiprocessing', '__builtins__', 'builtins', 'importlib', 'imp', 'code', 'codeop', 'compile', } # 允许的内置函数 ALLOWED_BUILTINS = { 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable', 'chr', 'complex', 'dict', 'dir', 'divmod', 'enumerate', 'filter', 'float', 'format', 'frozenset', 'getattr', 'hasattr', 'hash', 'hex', 'id', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'list', 'map', 'max', 'min', 'next', 'object', 'oct', 'ord', 'pow', 'print', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'str', 'sum', 'tuple', 'type', 'vars', 'zip', 'True', 'False', 'None', 'Exception', 'BaseException', 'ValueError', 'TypeError', 'KeyError', 'IndexError', 'AttributeError', 'RuntimeError', 'StopIteration', } class ScriptExecutor: """脚本执行器""" def __init__(self, db: Session): self.db = db def execute( self, script_content: str, task_id: int, tenant_id: Optional[str] = None, trace_id: Optional[str] = None, params: Optional[Dict[str, Any]] = None, timeout: int = 300 ) -> Tuple[bool, str, str, Optional[Dict]]: """执行脚本 Args: script_content: Python脚本内容 task_id: 任务ID tenant_id: 租户ID trace_id: 追踪ID params: 输入参数 timeout: 超时秒数 Returns: (success, output, error, result) result: 脚本返回值 {'content': '...', 'title': '...'} """ # 创建SDK实例 sdk = ScriptSDK( db=self.db, task_id=task_id, tenant_id=tenant_id, trace_id=trace_id, params=params or {} ) # 检查脚本安全性 check_result = self._check_script_safety(script_content) if check_result: return False, '', f"脚本安全检查失败: {check_result}", None # 准备执行环境 safe_globals = self._create_safe_globals(sdk) # 捕获输出 old_stdout = sys.stdout old_stderr = sys.stderr stdout_capture = StringIO() stderr_capture = StringIO() try: sys.stdout = stdout_capture sys.stderr = stderr_capture # 编译并执行脚本 compiled = compile(script_content, '