ChangranHuuu's picture
Upload 12 files
b43abc8 verified
"""
This module provides functions to extract and execute Python code from a string.
The functions are:
* extract_and_run_python_code(txt: str) -> str: Extracts and executes Python code from a string.
* execute_code_with_timeout(code: str, timeout: int = 3) -> str: Executes Python code with a timeout and returns the output.
Additional functions can be added as needed.
"""
import os
import tempfile
from subprocess import Popen, PIPE, TimeoutExpired
def extract_and_run_python_code(txt: str) -> str:
"""
Extract and execute Python code from a provided string.
Handles missing print statements for non-comment last lines,
executes the code, and captures output or errors.
Parameters:
txt (str): Input string containing a possible Python code block.
Returns:
str: Execution result or error message wrapped in output formatting.
"""
def extract_code(input_str: str) -> str:
"""Extract Python code block delimited by ```python and ```."""
try:
return input_str.split("```python", 1)[1].split("```", 1)[0].strip()
except IndexError:
raise ValueError("No valid Python code block found.")
def ensure_print_statement(code: str) -> str:
"""
Append a print statement if the last line isn't a comment or a print statement.
"""
lines = code.splitlines()
last_line = lines[-1].rstrip()
if not last_line.startswith(("print(", "#", " ", "\t")) and (not ("return" in last_line)):# and len((last_line.split(" "))) == 1:
lines[-1] = f"print({last_line})"
return "\n".join(lines)
if "```python" not in txt:
return None # Return early if no Python code block is present
try:
# Extract and sanitize the code
code_block = extract_code(txt)
code_with_print = ensure_print_statement(code_block)
# Execute the code and return output
python_output = execute_code_with_timeout(code_with_print)
# return f"PYTHON CODE OUTPUT:\n'''\n{python_output}\n'''"
return f"Output of the Python code above:\n```\n{python_output}\n```"
except Exception as error:
return f"PYTHON CODE OUTPUT:\n```\nError: {str(error)}\n```"
# Python code execution function with timeout
# TODO (msuzgun): Improve the security of this function by using a sandboxed environment
def execute_code_with_timeout(code: str, timeout: int = 3) -> str:
"""
Execute Python code with a timeout and return the output.
Parameters:
code (str): Python code to execute.
timeout (int): Timeout duration in seconds.
Returns:
str: Captured output or error message from the code execution.
"""
with tempfile.NamedTemporaryFile(
mode="w+t", suffix=".py", delete=False
) as temp_file:
temp_file.write(code)
temp_file.flush()
try:
# In case alias python=python3 is not set, use python3 instead of python
process = Popen(["python3", temp_file.name], stdout=PIPE, stderr=PIPE)
stdout, stderr = process.communicate(timeout=timeout)
captured_output = stdout.decode().strip()
error_output = stderr.decode().strip()
if captured_output == "":
if error_output != "":
captured_output = f"Error in execution: {error_output}"
else:
captured_output = "(No output was generated. It is possible that you did not include a print statement in your code. If you want to see the output, please include a print statement.)"
except TimeoutExpired:
process.kill()
captured_output = "Execution took too long, aborting..."
finally:
os.remove(temp_file.name)
return captured_output