import asyncio import sys import tempfile import os async def python_executor(code: str, timeout: int = 30) -> str: """执行 Python 代码片段并返回输出。 Args: code: 要执行的 Python 代码 timeout: 超时秒数,默认 30 秒 Returns: 代码的标准输出 + 标准错误 """ from kilostar.utils.sandbox import ( validate_python_code, CodeViolation, get_python_timeout, ) try: code = validate_python_code(code) except CodeViolation as e: return f"[Sandbox] {e}" timeout = get_python_timeout(timeout) tmp_file = None try: with tempfile.NamedTemporaryFile( mode="w", suffix=".py", delete=False, encoding="utf-8" ) as f: f.write(code) tmp_file = f.name proc = await asyncio.create_subprocess_exec( sys.executable, tmp_file, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, ) stdout, stderr = await asyncio.wait_for( proc.communicate(), timeout=timeout ) output = stdout.decode("utf-8", errors="replace") err_output = stderr.decode("utf-8", errors="replace") result = "" if output: result += output if err_output: result += f"\n[stderr]\n{err_output}" if proc.returncode != 0: result += f"\n[exit code: {proc.returncode}]" return result.strip() or "(no output)" except asyncio.TimeoutError: return f"[Error] Python 代码执行超时({timeout}s)" except Exception as e: return f"[Error] 执行失败: {e}" finally: if tmp_file and os.path.exists(tmp_file): os.unlink(tmp_file)