update python_execute safe

This commit is contained in:
836304831 2025-03-12 23:33:37 +08:00
parent b3c4f5ce22
commit ed4b78dc37

View File

@ -1,4 +1,6 @@
import threading import sys
from io import StringIO
import multiprocessing
from typing import Dict from typing import Dict
from app.tool.base import BaseTool from app.tool.base import BaseTool
@ -20,6 +22,20 @@ class PythonExecute(BaseTool):
"required": ["code"], "required": ["code"],
} }
def _run_code(self, code: str, result_dict: dict, safe_globals: dict) -> None:
original_stdout = sys.stdout
try:
output_buffer = StringIO()
sys.stdout = output_buffer
exec(code, safe_globals, safe_globals)
result_dict["observation"] = output_buffer.getvalue()
result_dict["success"] = True
except Exception as e:
result_dict["observation"] = str(e)
result_dict["success"] = False
finally:
sys.stdout = original_stdout
async def execute( async def execute(
self, self,
code: str, code: str,
@ -35,36 +51,29 @@ class PythonExecute(BaseTool):
Returns: Returns:
Dict: Contains 'output' with execution output or error message and 'success' status. Dict: Contains 'output' with execution output or error message and 'success' status.
""" """
result = {"observation": ""}
def run_code(): with multiprocessing.Manager() as manager:
try: result = manager.dict({
safe_globals = {"__builtins__": dict(__builtins__)} "observation": "",
"success": False
})
if isinstance(__builtins__, dict):
safe_globals = {"__builtins__": __builtins__}
else:
safe_globals = {"__builtins__": __builtins__.__dict__.copy()}
proc = multiprocessing.Process(
target=self._run_code,
args=(code, result, safe_globals)
)
proc.start()
proc.join(timeout)
import sys # timeout process
from io import StringIO if proc.is_alive():
proc.terminate()
output_buffer = StringIO() proc.join(1)
sys.stdout = output_buffer return {
"observation": f"Execution timeout after {timeout} seconds",
exec(code, safe_globals, {}) "success": False,
}
sys.stdout = sys.__stdout__ return dict(result)
result["observation"] = output_buffer.getvalue()
except Exception as e:
result["observation"] = str(e)
result["success"] = False
thread = threading.Thread(target=run_code)
thread.start()
thread.join(timeout)
if thread.is_alive():
return {
"observation": f"Execution timeout after {timeout} seconds",
"success": False,
}
return result