-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
112 lines (94 loc) · 3.19 KB
/
Copy pathapp.py
File metadata and controls
112 lines (94 loc) · 3.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
from flask import Flask, request, jsonify
from flask_cors import CORS
import docker
import uuid
import time
import base64
import io
import matplotlib
matplotlib.use('Agg') # Use non-interactive backend
import matplotlib.pyplot as plt
image_name = "python-code-runner13:latest"
app = Flask(__name__)
CORS(app)
client = docker.from_env() # Connect to Docker daemon
timeout = 10 # seconds
# Build the custom image if it doesn't exist
try:
client.images.get(image_name)
except docker.errors.ImageNotFound:
print("Building custom Python image...")
client.images.build(
path='./backend',
tag=image_name,
dockerfile='Dockerfile',
)
@app.route("/execute", methods=["POST"])
def execute_code():
data = request.get_json()
code = data.get("code")
if not code or len(code) == 0:
return jsonify({"output": "No code provided"}), 200
container_name = f"code-runner-{uuid.uuid4()}"
try:
print(f"Container {container_name} started with:\n{code}")
now = time.time()
# Add code to save plot to a file if matplotlib is used
plot_code = """
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import base64
import io
# Your code here
{}
# If there's a plot, save it to a file
if plt.get_fignums():
buf = io.BytesIO()
plt.savefig(buf, format='png')
buf.seek(0)
print('PLOT_START')
print(base64.b64encode(buf.getvalue()).decode())
print('PLOT_END')
plt.close('all')
""".format(code)
container = client.containers.run(
image_name,
name=container_name,
command=f"timeout {timeout}s python3 -c \"{plot_code.replace('"', '\\"')}\"",
detach=True,
remove=False,
mem_limit="128m",
network_disabled=True,
stdin_open=False,
tty=False,
)
exit_status = container.wait(timeout=timeout)
duration = time.time() - now
logs = container.logs(stdout=True, stderr=True).decode()
container.remove(force=True)
if exit_status["StatusCode"] == 124:
return jsonify({"output": f"Exedió el tiempo ({duration:.2f}s)"}), 200
# Check if there's a plot in the output
if 'PLOT_START' in logs and 'PLOT_END' in logs:
plot_data = logs.split('PLOT_START')[1].split('PLOT_END')[0].strip()
return jsonify({
"output": logs.split('PLOT_START')[0].strip(),
"plot": plot_data,
"status_code": exit_status["StatusCode"],
"duration": duration
}), 200
return jsonify({"output": logs.strip(),
"status_code": exit_status["StatusCode"],
"duration": duration
}), 200
except docker.errors.ContainerError as e:
return jsonify({"output": e.stderr.decode() if e.stderr else str(e),
"status_code": e.exit_status,
"error": "Container Error"
}), 400
except Exception as e:
print(f"Error: {e}")
return jsonify({"output": str(e)}), 500
if __name__ == "__main__":
app.run()