fastapi: 第十二章:用loguru记录异常

一,记录捕捉到的异常 

代码:

@router.get("/all")
def get_all_products():
    try:
        a = 0
        b = 100 / a
        print(b)
        products = [{"id": 1, "name": "手机"}, {"id": 2, "name": "电脑"}]
        return success(data=products)
    except Exception as e:
        logger.error("遇到了一个异常:{}", e)
        return fail(code=501,msg=f"获取产品时遇到异常:{e}")

测试效果:

image

查看日志:

2026-05-24 12:29:04.479 | ERROR    | app.api.products:get_all_products:18 - 遇到了一个异常:division by zero

二,记录全局异常

1,发生异常时记录数据:

说明:loguru的exception方法能记录详细的异常堆栈

    # 4. 捕获系统未知异常 (如: 代码崩溃、数据库连接断开 500)
    @app.exception_handler(Exception)
    async def all_exception_handler(request: Request, exc: Exception):
        # 注意:生产环境应将 exc 记录到日志系统(如 loguru)
        logger.exception(f"服务器内部崩溃 -> 路由: {request.url.path} | 方法: {request.method}")
        content = BaseResponse(code=500, msg="服务器内部错误,请稍后再试", data=None).model_dump()
        return JSONResponse(status_code=500, content=content)

2,查看日志内容:

2026-05-24 13:11:16.621 | ERROR    | app.core.exceptions:all_exception_handler:38 - 服务器内部崩溃 -> 路由: /products/all | 方法: GET
Traceback (most recent call last):

  File "<string>", line 1, in <module>
  File "/usr/local/soft/python3.10.19/lib/python3.10/multiprocessing/spawn.py", line 116, in spawn_main
    exitcode = _main(fd, parent_sentinel)
               │     │   └ 4
               │     └ 7
               └ <function _main at 0x7305fa0bbb50>
  File "/usr/local/soft/python3.10.19/lib/python3.10/multiprocessing/spawn.py", line 129, in _main
    return self._bootstrap(parent_sentinel)
           │    │          └ 4
           │    └ <function BaseProcess._bootstrap at 0x7305fa236200>
           └ <SpawnProcess name='SpawnProcess-11' parent=4179 started>
  File "/usr/local/soft/python3.10.19/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap
    self.run()
    │    └ <function BaseProcess.run at 0x7305fa235870>
    └ <SpawnProcess name='SpawnProcess-11' parent=4179 started>
  File "/usr/local/soft/python3.10.19/lib/python3.10/multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
    │    │        │    │        │    └ {'config': <uvicorn.config.Config object at 0x7305fa0cf220>, 'target': <bound method Server.run of <uvicorn.server.Server obj...
    │    │        │    │        └ <SpawnProcess name='SpawnProcess-11' parent=4179 started>
    │    │        │    └ ()
    │    │        └ <SpawnProcess name='SpawnProcess-11' parent=4179 started>
    │    └ <function subprocess_started at 0x7305f94c6e60>
    └ <SpawnProcess name='SpawnProcess-11' parent=4179 started>
  File "/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 80, in subprocess_started
    target(sockets=sockets)
    │              └ [<socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8000)>]
    └ <bound method Server.run of <uvicorn.server.Server object at 0x7305fa0cf280>>
  File "/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/uvicorn/server.py", line 75, in run
    return asyncio_run(self.serve(sockets=sockets), loop_factory=self.config.get_loop_factory())
           │           │    │             │                      │    │      └ <function Config.get_loop_factory at 0x7305f96bfa30>
           │           │    │             │                      │    └ <uvicorn.config.Config object at 0x7305fa0cf220>
           │           │    │             │                      └ <uvicorn.server.Server object at 0x7305fa0cf280>
           │           │    │             └ [<socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8000)>]
           │           │    └ <function Server.serve at 0x7305f94c5ea0>
           │           └ <uvicorn.server.Server object at 0x7305fa0cf280>
           └ <function asyncio_run at 0x7305f966e950>
  File "/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/uvicorn/_compat.py", line 60, in asyncio_run
    return loop.run_until_complete(main)
           │    │                  └ <coroutine object Server.serve at 0x7305f9489c40>
           │    └ <function BaseEventLoop.run_until_complete at 0x7305f986d630>
           └ <_UnixSelectorEventLoop running=True closed=False debug=False>
  File "/usr/local/soft/python3.10.19/lib/python3.10/asyncio/base_events.py", line 636, in run_until_complete
    self.run_forever()
    │    └ <function BaseEventLoop.run_forever at 0x7305f986d5a0>
    └ <_UnixSelectorEventLoop running=True closed=False debug=False>
  File "/usr/local/soft/python3.10.19/lib/python3.10/asyncio/base_events.py", line 603, in run_forever
    self._run_once()
    │    └ <function BaseEventLoop._run_once at 0x7305f986f0a0>
    └ <_UnixSelectorEventLoop running=True closed=False debug=False>
  File "/usr/local/soft/python3.10.19/lib/python3.10/asyncio/base_events.py", line 1909, in _run_once
    handle._run()
    │      └ <function Handle._run at 0x7305f99ce440>
    └ <Handle Task.task_wakeup(<Future finis...ion by zero')>)>
  File "/usr/local/soft/python3.10.19/lib/python3.10/asyncio/events.py", line 80, in _run
    self._context.run(self._callback, *self._args)
    │    │            │    │           │    └ <member '_args' of 'Handle' objects>
    │    │            │    │           └ <Handle Task.task_wakeup(<Future finis...ion by zero')>)>
    │    │            │    └ <member '_callback' of 'Handle' objects>
    │    │            └ <Handle Task.task_wakeup(<Future finis...ion by zero')>)>
    │    └ <member '_context' of 'Handle' objects>
    └ <Handle Task.task_wakeup(<Future finis...ion by zero')>)>
  File "/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/uvicorn/protocols/http/h11_impl.py", line 415, in run_asgi
    result = await app(  # type: ignore[func-returns-value]
                   └ <uvicorn.middleware.proxy_headers.ProxyHeadersMiddleware object at 0x7305f95099c0>
  File "/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/uvicorn/middleware/proxy_headers.py", line 56, in __call__
    return await self.app(scope, receive, send)
                 │    │   │      │        └ <bound method RequestResponseCycle.send of <uvicorn.protocols.http.h11_impl.RequestResponseCycle object at 0x7305f7c47d90>>
                 │    │   │      └ <bound method RequestResponseCycle.receive of <uvicorn.protocols.http.h11_impl.RequestResponseCycle object at 0x7305f7c47d90>>
                 │    │   └ {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.3'}, 'http_version': '1.1', 'server': ('127.0.0.1', 8000), 'cl...
                 │    └ <fastapi.applications.FastAPI object at 0x7305f9509b70>
                 └ <uvicorn.middleware.proxy_headers.ProxyHeadersMiddleware object at 0x7305f95099c0>
  File "/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/fastapi/applications.py", line 1159, in __call__
    await super().__call__(scope, receive, send)
                           │      │        └ <bound method RequestResponseCycle.send of <uvicorn.protocols.http.h11_impl.RequestResponseCycle object at 0x7305f7c47d90>>
                           │      └ <bound method RequestResponseCycle.receive of <uvicorn.protocols.http.h11_impl.RequestResponseCycle object at 0x7305f7c47d90>>
                           └ {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.3'}, 'http_version': '1.1', 'server': ('127.0.0.1', 8000), 'cl...
  File "/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/starlette/applications.py", line 90, in __call__
    await self.middleware_stack(scope, receive, send)
          │    │                │      │        └ <bound method RequestResponseCycle.send of <uvicorn.protocols.http.h11_impl.RequestResponseCycle object at 0x7305f7c47d90>>
          │    │                │      └ <bound method RequestResponseCycle.receive of <uvicorn.protocols.http.h11_impl.RequestResponseCycle object at 0x7305f7c47d90>>
          │    │                └ {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.3'}, 'http_version': '1.1', 'server': ('127.0.0.1', 8000), 'cl...
          │    └ <starlette.middleware.errors.ServerErrorMiddleware object at 0x7305f7c6ca00>
          └ <fastapi.applications.FastAPI object at 0x7305f9509b70>
> File "/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/starlette/middleware/errors.py", line 164, in __call__
    await self.app(scope, receive, _send)
          │    │   │      │        └ <function ServerErrorMiddleware.__call__.<locals>._send at 0x7305f7c7c5e0>
          │    │   │      └ <bound method RequestResponseCycle.receive of <uvicorn.protocols.http.h11_impl.RequestResponseCycle object at 0x7305f7c47d90>>
          │    │   └ {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.3'}, 'http_version': '1.1', 'server': ('127.0.0.1', 8000), 'cl...
          │    └ <starlette.middleware.exceptions.ExceptionMiddleware object at 0x7305f7c6ca30>
          └ <starlette.middleware.errors.ServerErrorMiddleware object at 0x7305f7c6ca00>
  File "/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/starlette/middleware/exceptions.py", line 63, in __call__
    await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
          │                            │    │    │     │      │        └ <function ServerErrorMiddleware.__call__.<locals>._send at 0x7305f7c7c5e0>
          │                            │    │    │     │      └ <bound method RequestResponseCycle.receive of <uvicorn.protocols.http.h11_impl.RequestResponseCycle object at 0x7305f7c47d90>>
          │                            │    │    │     └ {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.3'}, 'http_version': '1.1', 'server': ('127.0.0.1', 8000), 'cl...
          │                            │    │    └ <starlette.requests.Request object at 0x7305f7c6c520>
          │                            │    └ <fastapi.middleware.asyncexitstack.AsyncExitStackMiddleware object at 0x7305f7c6ca90>
          │                            └ <starlette.middleware.exceptions.ExceptionMiddleware object at 0x7305f7c6ca30>
          └ <function wrap_app_handling_exceptions at 0x7305f8719f30>
  File "/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
    raise exc
  File "/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/starlette/_exception_handler.py", line 42, in wrapped_app
    await app(scope, receive, sender)
          │   │      │        └ <function wrap_app_handling_exceptions.<locals>.wrapped_app.<locals>.sender at 0x7305f7c7c670>
          │   │      └ <bound method RequestResponseCycle.receive of <uvicorn.protocols.http.h11_impl.RequestResponseCycle object at 0x7305f7c47d90>>
          │   └ {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.3'}, 'http_version': '1.1', 'server': ('127.0.0.1', 8000), 'cl...
          └ <fastapi.middleware.asyncexitstack.AsyncExitStackMiddleware object at 0x7305f7c6ca90>
  File "/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/fastapi/middleware/asyncexitstack.py", line 18, in __call__
    await self.app(scope, receive, send)
          │    │   │      │        └ <function wrap_app_handling_exceptions.<locals>.wrapped_app.<locals>.sender at 0x7305f7c7c670>
          │    │   │      └ <bound method RequestResponseCycle.receive of <uvicorn.protocols.http.h11_impl.RequestResponseCycle object at 0x7305f7c47d90>>
          │    │   └ {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.3'}, 'http_version': '1.1', 'server': ('127.0.0.1', 8000), 'cl...
          │    └ <fastapi.routing.APIRouter object at 0x7305f7c6c070>
          └ <fastapi.middleware.asyncexitstack.AsyncExitStackMiddleware object at 0x7305f7c6ca90>
  File "/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/starlette/routing.py", line 660, in __call__
    await self.middleware_stack(scope, receive, send)
          │    │                │      │        └ <function wrap_app_handling_exceptions.<locals>.wrapped_app.<locals>.sender at 0x7305f7c7c670>
          │    │                │      └ <bound method RequestResponseCycle.receive of <uvicorn.protocols.http.h11_impl.RequestResponseCycle object at 0x7305f7c47d90>>
          │    │                └ {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.3'}, 'http_version': '1.1', 'server': ('127.0.0.1', 8000), 'cl...
          │    └ <bound method Router.app of <fastapi.routing.APIRouter object at 0x7305f7c6c070>>
          └ <fastapi.routing.APIRouter object at 0x7305f7c6c070>
  File "/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/starlette/routing.py", line 680, in app
    await route.handle(scope, receive, send)
          │     │      │      │        └ <function wrap_app_handling_exceptions.<locals>.wrapped_app.<locals>.sender at 0x7305f7c7c670>
          │     │      │      └ <bound method RequestResponseCycle.receive of <uvicorn.protocols.http.h11_impl.RequestResponseCycle object at 0x7305f7c47d90>>
          │     │      └ {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.3'}, 'http_version': '1.1', 'server': ('127.0.0.1', 8000), 'cl...
          │     └ <function Route.handle at 0x7305f871b640>
          └ APIRoute(path='/products/all', name='get_all_products', methods=['GET'])
  File "/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/starlette/routing.py", line 276, in handle
    await self.app(scope, receive, send)
          │    │   │      │        └ <function wrap_app_handling_exceptions.<locals>.wrapped_app.<locals>.sender at 0x7305f7c7c670>
          │    │   │      └ <bound method RequestResponseCycle.receive of <uvicorn.protocols.http.h11_impl.RequestResponseCycle object at 0x7305f7c47d90>>
          │    │   └ {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.3'}, 'http_version': '1.1', 'server': ('127.0.0.1', 8000), 'cl...
          │    └ <function request_response.<locals>.app at 0x7305f7c43490>
          └ APIRoute(path='/products/all', name='get_all_products', methods=['GET'])
  File "/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/fastapi/routing.py", line 134, in app
    await wrap_app_handling_exceptions(app, request)(scope, receive, send)
          │                            │    │        │      │        └ <function wrap_app_handling_exceptions.<locals>.wrapped_app.<locals>.sender at 0x7305f7c7c670>
          │                            │    │        │      └ <bound method RequestResponseCycle.receive of <uvicorn.protocols.http.h11_impl.RequestResponseCycle object at 0x7305f7c47d90>>
          │                            │    │        └ {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.3'}, 'http_version': '1.1', 'server': ('127.0.0.1', 8000), 'cl...
          │                            │    └ <starlette.requests.Request object at 0x7305f7c47cd0>
          │                            └ <function request_response.<locals>.app.<locals>.app at 0x7305f7c7c700>
          └ <function wrap_app_handling_exceptions at 0x7305f8719f30>
  File "/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
    raise exc
  File "/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/starlette/_exception_handler.py", line 42, in wrapped_app
    await app(scope, receive, sender)
          │   │      │        └ <function wrap_app_handling_exceptions.<locals>.wrapped_app.<locals>.sender at 0x7305f7c7c790>
          │   │      └ <bound method RequestResponseCycle.receive of <uvicorn.protocols.http.h11_impl.RequestResponseCycle object at 0x7305f7c47d90>>
          │   └ {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.3'}, 'http_version': '1.1', 'server': ('127.0.0.1', 8000), 'cl...
          └ <function request_response.<locals>.app.<locals>.app at 0x7305f7c7c700>
  File "/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/fastapi/routing.py", line 120, in app
    response = await f(request)
                     │ └ <starlette.requests.Request object at 0x7305f7c47cd0>
                     └ <function get_request_handler.<locals>.app at 0x7305f7c43520>
  File "/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/fastapi/routing.py", line 674, in app
    raw_response = await run_endpoint_function(
                         └ <function run_endpoint_function at 0x7305f8739480>
  File "/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/fastapi/routing.py", line 330, in run_endpoint_function
    return await run_in_threadpool(dependant.call, **values)
                 │                 │         │       └ {}
                 │                 │         └ <function get_all_products at 0x7305f8674ca0>
                 │                 └ Dependant(path_params=[], query_params=[], header_params=[], cookie_params=[], body_params=[], dependencies=[], name=None, ca...
                 └ <function run_in_threadpool at 0x7305f89081f0>
  File "/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/starlette/concurrency.py", line 32, in run_in_threadpool
    return await anyio.to_thread.run_sync(func)
                 │     │         │        └ functools.partial(<function get_all_products at 0x7305f8674ca0>)
                 │     │         └ <function run_sync at 0x7305f9416560>
                 │     └ <module 'anyio.to_thread' from '/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/anyio/to_thread.py'>
                 └ <module 'anyio' from '/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/anyio/__init__.py'>
  File "/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/anyio/to_thread.py", line 63, in run_sync
    return await get_async_backend().run_sync_in_worker_thread(
                 └ <function get_async_backend at 0x7305f9415ea0>
  File "/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 2518, in run_sync_in_worker_thread
    return await future
                 └ <Future finished exception=ZeroDivisionError('division by zero')>
  File "/data/python/fastapi/demo1/venv/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 1002, in run
    result = context.run(func, *args)

  File "/data/python/fastapi/demo1/app/api/products.py", line 12, in get_all_products
    b = 100 / a
              └ 0

ZeroDivisionError: division by zero

 

posted @ 2026-06-10 15:19  刘宏缔的架构森林  阅读(5)  评论(0)    收藏  举报