Backend Eksekusi Kode Python โ FLOWER
Dokumen ini menjelaskan cara kerja backend eksekusi interaktif untuk latihan koding Python di platform FLOWER. Backend ini berjalan dalam container Docker tersendiri, dan dapat dipanggil oleh frontend melalui API POST ke endpoint /run
.
๐ง Struktur Sistem
- Bahasa yang didukung: Python 3.x
- Format komunikasi: JSON
- Server: Flask +
pexpect
- Port default:
5010
- Container name:
eksekutor
๐ฆ File Utama: api_eksekusi.py
from flask import Flask, request, jsonify
import tempfile
import os
import pexpect
import shutil
app = Flask(__name__)
@app.route("/run", methods=["POST"])
def run_code():
kode = request.json.get("kode", "")
stdin = request.json.get("stdin", "")
with tempfile.NamedTemporaryFile("w+", suffix=".py", delete=False) as f:
f.write(kode)
f.flush()
file_path = f.name
try:
python_path = shutil.which("python3") or "python3"
child = pexpect.spawn(f"{python_path} {file_path}", encoding="utf-8", timeout=5)
output = ""
stdin_lines = stdin.strip().splitlines()
input_index = 0
while True:
try:
idx = child.expect([pexpect.EOF, r":\s*$", r"\?\s*$", r">+\s*$", r".+?:\s*"])
output += child.before
if idx == 0:
break
if input_index < len(stdin_lines):
child.sendline(stdin_lines[input_index])
input_index += 1
else:
child.sendline("")
except pexpect.exceptions.TIMEOUT:
output += "\nโ ๏ธ Timeout: Program terlalu lama atau loop?"
break
output += child.read()
return jsonify({
"output": output.strip(),
"error": ""
})
except Exception as e:
return jsonify({
"output": "",
"error": str(e)
}), 500
finally:
if os.path.exists(file_path):
os.remove(file_path)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5010, debug=False)
๐ณ Dockerfile
FROM python:3.10-slim
WORKDIR /app
COPY . /app
RUN pip install --no-cache-dir flask pexpect
CMD ["python", "api_eksekusi.py"]
๐ Deployment via Docker
Build image:
docker build -t python-api .
Jalankan container:
docker run -d --name eksekutor -p 5010:5010 python-api
๐ค Endpoint API
URL:
POST /run
Header:
Content-Type: application/json
Body (JSON):
{
"kode": "print('Hello')",
"stdin": ""
}
Contoh dengan input:
{
"kode": "nama = input('Siapa nama kamu? ')\nprint('Halo', nama)",
"stdin": "Alya"
}
Response (JSON):
{
"output": "Siapa nama kamu? \nHalo Alya",
"error": ""
}
๐ก๏ธ Keunggulan pexpect
dibanding subprocess
Fitur | subprocess.run | pexpect |
---|---|---|
Dukungan input() interaktif | โ ๏ธ Terbatas | โ Ya |
Prompt tampil natural | โ Tidak | โ Ya |
Simulasi terminal asli | โ Tidak | โ Ya |
Menangani looping dan timeout | โ ๏ธ Sulit | โ Ya |
๐ Catatan Keamanan
- Backend ini hanya digunakan secara internal dari aplikasi FLOWER.
- Tidak disarankan untuk menerima kode dari publik tanpa sandbox tambahan.
- Waktu eksekusi dibatasi (
timeout=5
detik) agar tidak infinite loop.
๐งช Tes Lokal (Opsional)
Gunakan curl
untuk mengetes langsung:
curl -X POST http://localhost:5010/run \
-H "Content-Type: application/json" \
-d '{"kode": "a = input(\"Nama?\")\nprint(\"Hai\", a)", "stdin": "Reza"}'
โ Status: Aktif
Pastikan container berjalan:
docker ps