fastapi icon indicating copy to clipboard operation
fastapi copied to clipboard

sys.excepthook not work

Open wangdh1027 opened this issue 5 years ago • 5 comments

def my_excepthook(exc_type, exc_value, tb):
       if issubclass(exc_type, KeyboardInterrupt):
              sys.__excepthook__(exc_type, exc_value, tb)
              return
       msg = ' Traceback (most recent call last):\n'
       for filename, linenum, funcname, source in traceback.extract_tb(tb):
              msg += "%-23s:%s '%s' in %s() \n" % (filename, linenum, source, funcname)
       msg += ' %s: %s\n' %(exc_type.__name__, exc_value)
       logger.info(json.dumps({'msg':msg}))
sys.excepthook = my_excepthook

I want to use my_excepthook to process except, but it is not work in fastapi

wangdh1027 avatar Oct 14 '20 09:10 wangdh1027

Why do you think this is related to fastapi?

Mause avatar Oct 14 '20 09:10 Mause

Why do you think this is related to fastapi?

I write my_excepthook() in main.py if execute python main.py ,my_excepthook() is work if execute uvicorn main:app --reload --port 8818 --host 0.0.0.0, my_excepthook() is not work

wangdh1027 avatar Oct 14 '20 09:10 wangdh1027

I think the same as @wangdh1027. when I run my app as regular way lik "python main.py" hook catched the exception. But when I am running app via uvicorn it can not catch

msamancioglu avatar Nov 03 '21 18:11 msamancioglu

Hi all,

I know this issue is quite old, I think I can still provide an answer and have this one closed.

The reason for this is not FastAPI, its Uvicorn which is overriding the default behaviour. Instead of using the excepthook, I would recommend a different approach, which is more natural to FastAPI.

# Install middleware to catch all exceptions
@app.middleware("http")
async def exception_handler(request: Request, call_next):

    try:
        return await call_next(request)
    except Exception as e:
        logger.error("An unexpected error occured during request: {0}".format(str(e)))
        logger.info(
            "Traceback is: {0}".format(str(traceback.format_tb(e.__traceback__, 10)))
        )

        return JSONResponse(
            content={
                "message": "Unexpected error occured during request processing. Our team has been notified."
            },
            status_code=500,
        )

This approach uses a HTTP middleware and wraps all the processing of the actual request into a try/except block. This way, all exceptions caused by the application code can be caught and handled (including proper logging) and you can even send a meaningful reply to the API client.

Hope this helps.

waza-ari avatar Jul 09 '22 15:07 waza-ari

The solution above sounds fine though it does not catch exceptions raised during app startup (i.e. @app.on_event("startup")) .

marcilioLemos avatar Sep 16 '22 14:09 marcilioLemos

@marcilioLemos for that you can use a regular sys.excepthook?

fredrikaverpil avatar Sep 29 '22 06:09 fredrikaverpil

@marcilioLemos for that you can use a regular sys.excepthook?

That doesn't work when run via uvicorn.run() as described by @waza-ari.

alenzo-pinc avatar Oct 06 '22 15:10 alenzo-pinc

I need to add a word of warning here - I had to remove the workaround I described earlier due to the FastAPI upgrade to 0.85 and consequently a starlette upgrade.

Details can be found here: https://stackoverflow.com/questions/73927410/pytest-fixtures-sqalchemy-connections-not-closing-when-running-in-docker

waza-ari avatar Oct 06 '22 15:10 waza-ari

I need to add a word of warning here - I had to remove the workaround I described earlier due to the FastAPI upgrade to 0.85 and consequently a starlette upgrade.

Details can be found here: https://stackoverflow.com/questions/73927410/pytest-fixtures-sqalchemy-connections-not-closing-when-running-in-docker

Interesting.... I wonder if you could have raised and HTTPException in the middleware to get your session dependency to close the connection and roll back?

alenzo-pinc avatar Oct 06 '22 20:10 alenzo-pinc