繁体   English   中英

run_in_executor 会阻塞吗?

[英]Will run_in_executor ever block?

假设如果我有这样的 web 服务器:

from fastapi import FastAPI
import uvicorn
import asyncio

app = FastAPI()

def blocking_function():
    import time
    time.sleep(5)
    return 42

@app.get("/")
async def root():
    loop = asyncio.get_running_loop()

    result = await loop.run_in_executor(None, blocking_function)
    return result

@app.get("/ok")
async def ok():
    return {"ok": 1}

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", workers=1)

据我了解,代码将在默认的 ThreadExecutorPool 中生成另一个线程,然后在线程池中执行阻塞 function。 另一方面,考虑到 GIL 的工作原理,CPython 解释器只会执行一个线程 100 个ticks ,然后它会切换到另一个线程以公平地给其他线程一个进步的机会。 在这种情况下,如果 Python 解释器决定切换到执行 blocking_function 的线程会怎样? 它会阻止 who 解释器等待time.sleep(5)上剩余的任何内容吗?

我问这个的原因是我观察到我的应用程序有时会blocking_function ,但是我不完全确定这里发生了什么,因为我的blocking_function非常特别——它通过 win32com 库与 COM API object 对话。 我试图排除这是我掉入的一些 GIL 陷阱。

time.sleep (正如这个问题中所解释的)和win32com库(根据这个邮件列表帖子)在它们被调用时释放 GIL,因此它们不会阻止其他线程在阻塞时取得进展。

要回答“高级”问题——“ run_in_executor是否可以(直接或间接)阻止事件循环?” - 如果您使用ThreadPoolExecutor并且您在run_in_executor中执行的代码执行了未释放 GIL 的阻塞工作,则答案只会是“是”。 虽然这不会完全阻塞事件循环,但这意味着您的事件循环线程和执行程序线程无法并行运行,因为两者都需要获取 GIL 才能取得进展。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM