defexec_last_expr(code: str): """Execute the code and return the result or error message. Args: code (str): 需要执行的代码字符串。 Returns: 任意: 返回最后一个表达式的结果或错误信息。 """ local_vars = {} # Split the code into lines lines = code.strip().split('\n') try: # Execute all lines except the last one exec('\n'.join(lines[:-1]), {}, local_vars) # Evaluate the last expression result = eval(lines[-1], {}, local_vars) return result except Exception as e: returnstr(e)
用法示例:exec_python_code
简单的变量赋值
1 2 3 4 5 6 7 8
code = """ x = 10 y = 20 z = x + y """
result = exec_python_code(code) print(result)
输出
1
{'x': '10', 'y': '20', 'z': '30'}
函数定义和调用
1 2 3 4 5 6 7 8 9
code = """ def add(a, b): return a + b result = add(5, 7) """
result = exec_python_code(code) print(result)
输出
1
{'add': '<function add at 0x....>', 'result': '12'}
循环和条件语句
1 2 3 4 5 6 7 8 9
code = """ result_list = [] for i in range(5): if i % 2 == 0: result_list.append(i) """
result = exec_python_code(code) print(result)
输出
1
{'result_list': '[0, 2, 4]', 'i': '4'}
捕获错误
1 2 3 4 5 6 7 8
code = """ a = 5 b = 0 c = a / b """
result = exec_python_code(code) print(result)
输出
1
{'error': 'division by zero'}
用法示例:exec_last_expr
和前边类似,但要在末尾追加希望求解的变量。
简单数学计算:
1 2 3 4 5 6 7 8
code = """ a = 10 b = 5 a + b """
result = exec_last_expr(code) print(result)
输出
1
15
使用列表和列表推导式:
1 2 3 4 5 6 7 8
code = """ numbers = [1, 2, 3, 4, 5] squared_numbers = [n**2 for n in numbers] squared_numbers """
with tempfile.TemporaryDirectory() as temp_dir: # create a temporary file with the Python code temp_file_path = os.path.join(temp_dir, "tmp.py") withopen(temp_file_path, "w") as f: f.write(query)
# execute the Python code result = subprocess.run( [self.python_executable, temp_file_path], capture_output=True, check=False, text=True, timeout=self.timeout, )
# return the output or error message if result.returncode == 0: output = result.stdout returnTrue, output.strip() else: msgs = result.stderr.strip().split("\n") # return False, '\n'.join(msgs.strip()) # return the full error message new_msgs = [] want_next = False for m in msgs[:-1]: # catch the traceback error message if"Traceback"in m: new_msgs.append(m) elif temp_file_path in m: new_msgs.append(m.replace(temp_file_path, "tmp.py")) want_next = True elif want_next: new_msgs.append(m) want_next = False new_msgs.append(msgs[-1]) error_msg = "\n".join(new_msgs).strip() returnFalse, error_msg defcode_check(self, query: str) -> Tuple[bool, str]: """Check if the code contains disallowed libraries""" # skip the check for now # disallowed = ["subprocess", "venv"] # for lib in disallowed: # if lib in query: # return False, f"Disallowed library '{lib}' found in the code." returnTrue, ""
def__call__(self, query: str) -> Tuple[bool, str]: # submit the execution in a thread pool with ThreadPoolExecutor() as executor: future = executor.submit(self.execute, query) try: return future.result(timeout=self.timeout) except TimeoutError: returnFalse, f"Timed out after {self.timeout} seconds."
False Traceback (most recent call last): File "tmp.py", line 5, in <module> print(x / 0) ZeroDivisionError: division by zero
嵌套调用的错误:当函数嵌套调用失败时,它同样能够捕获完整的堆栈跟踪信息。
1 2 3 4 5 6 7 8 9 10 11 12
query = """ def fetch_area(circle): return circle.area() class Circle: def __init__(self, radius): self.radius = radius # Calling fetch_area with an object that doesn't have an 'area' method c = Circle(5) fetch_area(c) """ success, output = repl(query) print(success, output)
输出
1 2 3 4 5 6
False Traceback (most recent call last): File "tmp.py", line 14, in <module> print(fetch_area(c)) File "tmp.py", line 6, in fetch_area return circle.area() AttributeError: 'Circle' object has no attribute 'area'