suppose if I have a web server like this:
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)
As I understand, the code will spawn another thread in the default ThreadExecutorPool and then execute the blocking function in the thread pool. On the other side, thinking about how the GIL works, the CPython interpreter will only execute a thread for 100 ticks
and then it will switch to another thread to be fair and give other threads a chance to progress. In this case, what if the Python interpreter decides to switch to the threads where the blocking_function is executing? Will it block the who interpreter to wait for whatever remaining on the time.sleep(5)
?
The reason I am asking this is that I have observed sometimes my application will block on the blocking_function
, however I am not entirely sure what's in play here as my blocking_function
is quite special -- it talks to a COM API object through the win32com library. I am trying to rule out that this is some GIL pitfalls I am falling into.