FastAPI/Starlette: How to handle exceptions inside background tasks?

Question:

I developed some API endpoints using FastAPI. These endpoints are allowed to run BackgroundTasks. Unfortunately, I do not know how to handle unpredictable issues from theses tasks.

An example of my API is shown below:

# main.py

from fastapi import FastAPI
import uvicorn


app = FastAPI()


def test_func(a, b):
    raise ...


@app.post("/test", status_code=201)
async def test(request: Request, background_task: BackgroundTasks):
    background_task.add_task(test_func, a, b)
    return {
        "message": "The test task was successfully sent.",
    }
if __name__ == "__main__":
    uvicorn.run(
        app=app,
        host="0.0.0.0",
        port=8000
    )
# python3 main.py to run
# fastapi == 0.78.0
# uvicorn == 0.16.0

Can you help me to handle any type of exception from such a background task?
Should I add any exception_middleware from Starlette, in order to achieve this?

Asked By: PicxyB

||

Answers:

Can you help me to handle any type of exception from such a background task?

Background tasks, as the name suggests, are tasks that are going to run in the background after returning a response. Hence, you can’t raise an Exception and expect the client to receive some kind of response. If you are just looking to catch any Exception occuring inside the backround task, you can simply use the try-except block to catch any Exception and handle it as desired. For example:

def test_func(a, b):
    try:
        # some background task logic here...
        raise <some_exception>
    except Exception as e:
        print('Something went wrong')
        # use `print(e.detail)` to print out the Exception's details 

If you would like to log any exceptions being raised in the task (instead of just printing them out), you could use Python’s logging module—have a look at this answer, as well as this answer and this answer on how to do that. You may also find helpful information on FastAPI/Starlette’s custom/global exception handlers at this post and this post, as well as here, here and here.

Finally, this answer will help you understand in detail the difference between def and async def endpoints (as well as background task functions) in FastAPI, and find solutions for tasks blocking the event loop (if you ever come across this issue).

Answered By: Chris

I’m not 100% sure what you mean by "unpredictable errors"and what would be the behavior if an exception occurs?

A try/except statement could work.

# main.py

from fastapi import FastAPI
import uvicorn


app = FastAPI()


def test_func(a, b):
    raise ...


@app.post("/test", status_code=201)
async def test(request: Request, background_task: BackgroundTasks):
    try:
        background_task.add_task(test_func, a, b)
        return {
            "message": "The test task was successfully sent.",
        }
    except Exception as e:
        # exception handling code
if __name__ == "__main__":
    uvicorn.run(
        app=app,
        host="0.0.0.0",
        port=8000
    )
# python3 main.py to run
# fastapi == 0.78.0
# uvicorn == 0.16.0
Answered By: Stefan