executor / jupyter_kernel.py
leandro
index
ecdfb50
from flask import Flask, request, jsonify, send_from_directory
from jupyter_client import KernelManager
import sys, io, time, queue, os
app = Flask(__name__, static_url_path='/static', static_folder='static')
TIMEOUT = os.getenv("TIMEOUT", 60)
km = KernelManager(kernel_name='python3')
km.start_kernel()
kc = km.client()
@app.route("/", methods=["HEAD", "GET"])
def index():
return send_from_directory(directory="static", path="index.html")
@app.route('/execute', methods=['POST'])
def execute_code():
global kc
code = request.json.get('code')
if not code:
return jsonify({'error': 'No code provided'}), 400
outputs = []
start_time = time.time()
_ = kc.execute(code)
success = True
error = None
while True:
try:
# if we timed out we interrupt the kernel so we can send the next request
if time.time() - start_time > TIMEOUT:
outputs.append({"text": f"Code execution has timed out (max {TIMEOUT}sec)."})
success = False
error = "TimeOut"
km.interrupt_kernel()
break
# get message from output buffer
msg = kc.get_iopub_msg(timeout=1)
# if the kernel is idle again we can wrap up
if msg['header']['msg_type'] == 'status' and msg['content']['execution_state'] == 'idle':
break
# save output messages
if msg['header']['msg_type'] == 'stream':
outputs.append({"text": msg['content']['text']})
# handle error messages
elif msg['header']['msg_type'] == 'error':
outputs.append({"text": "\n".join(msg['content']['traceback'])})
success = False
error = msg["content"]["ename"]
# handle figures
elif msg['header']['msg_type'] == 'display_data':
msg["content"]["data"]["text"] = msg["content"]["data"].pop("text/plain")
outputs.append(msg["content"]["data"])
# if queue is empty we try again, unless the kernel is dead
except queue.Empty:
print("No message received (timeout)", )
if not kc.is_alive():
outputs.append({"text": "Kernel has died!"})
success = False
error = "KernelDied"
km.restart_kernel()
break
return jsonify({
'result': outputs,
'success': success,
'error': error
})
@app.route('/restart', methods=['POST'])
def restart_kernel():
global kc
km.restart_kernel()
kc = km.client()
return jsonify(status="Kernel has been restarted."), 200
@app.route('/health', methods=['GET'])
def health_check():
return jsonify(status="healthy"), 200
if __name__ == '__main__':
app.run(host='0.0.0.0', port=7860)