python-3.x 如何从快速API内部运行jupyter内核?

5t7ly7z5  于 2023-08-08  发布在  Python
关注(0)|答案(1)|浏览(176)

我正在尝试做一些简单的事情--从fastAPI路由内执行jupyter notebook内核中的代码。
这是我所知道:

from fastapi import FastAPI, HTTPException, Body
from jupyter_client import KernelManager
from jupyter_client.blocking.client import BlockingKernelClient

app = FastAPI()
km = KernelManager(kernel_name="python3")
client = km.client()

def execute_code():
    msg_id = client.execute("time.sleep(10)")
    print(msg_id)
    while True:
        try:
            reply = client.get_shell_msg(timeout=1)
            if reply['parent_header']['msg_id'] == msg_id:
                if reply['content']['status'] == 'error':
                    return {"error_type": "failed_to_execute", 'error': '\n'.join(reply['content']['traceback'])}
                break
        except Empty:
            pass

        try:
            iopub_msg = client.get_iopub_msg(timeout=1)
            print(iopub_msg)
            break
        except Empty:
            pass

    return {"result": "success"}

                
@app.post("/execute_cell")
async def execute_cell() -> dict:
    try:
        execute_code()
    except Exception as e:
        print(e)
        raise HTTPException(status_code=500, detail={"error_type": "failed_to_execute_internal", "error": str(e)})

字符串
这给了我一个错误:

Traceback (most recent call last):
  File "/home/vedantroy/miniconda3/lib/python3.10/asyncio/events.py", line 80, in _run
    self._context.run(self._callback, *self._args)
RuntimeError: Cannot enter into task <Task pending name='Task-1' coro=<Server.serve() running at /home/vedantroy/miniconda3/lib/python3.10/site-packages/uvicorn/server.py:81> wait_for=<Future finished result=None> cb=[_run_until_complete_cb() at /home/vedantroy/miniconda3/lib/python3.10/asyncio/base_events.py:184]> while another task <Task pending name='Task-5' coro=<RequestResponseCycle.run_asgi() running at /home/vedantroy/miniconda3/lib/python3.10/site-packages/uvicorn/protocols/http/h11_impl.py:428> cb=[set.discard()]> is being executed.


这看起来像是Task-1试图被调度到事件循环中,而另一个任务正在执行。
如何修复此错误?

esyap4oy

esyap4oy1#

您遇到的错误与尝试在异步上下文中执行阻塞操作有关。您正在使用的execute_code()函数包含了对client.execute()和client.get_shell_msg()的阻塞调用,这与FastAPI的异步特性不兼容。
若要修复此问题,可以使用后台任务异步执行代码。FastAPI为此提供了BackgroundTasks类。

from fastapi import FastAPI, HTTPException, BackgroundTasks
from jupyter_client import KernelManager
from jupyter_client.blocking.client import BlockingKernelClient

def execute_cell(background_tasks: BackgroundTasks):
    background_tasks.add_task(execute_code)

@app.post("/execute_cell")
async def execute_cell_endpoint(background_tasks: BackgroundTasks) -> dict:
    try:
        execute_cell(background_tasks)
        return {"status": "success", "message": "Code execution started."}
    except Exception as e:
        print(e)
        raise HTTPException(status_code=500, detail={"error_type": "failed_to_execute_internal", "error": str(e)})

字符串

相关问题