Estoy usando FastAPI con Pydantic.
Mi problema: necesito aumentar ValueError usando Pydantic
from fastapi import FastAPI from pydantic import BaseModel, validator from fastapi import Depends, HTTPException app = FastAPI() class RankInput(BaseModel): rank: int @validator('rank') def check_if_value_in_range(cls, v): """ check if input rank is within range """ if not 0 < v < 1000001: raise ValueError("Rank Value Must be within range (0,1000000)") #raise HTTPException(status_code=400, detail="Rank Value Error") - this works But I am looking for a solution using ValueError return v def get_info_by_rank(rank): return rank @app.get('/rank/{rank}') async def get_rank(value: RankInput = Depends()): result = get_info_by_rank(value.rank) return result este fragmento de código da un Internal Server Error cuando se genera un ValueError
INFO: 127.0.0.1:59427 - "GET /info/?rank=-1 HTTP/1.1" 500 Internal Server Error ERROR: Exception in ASGI application Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/uvicorn/protocols/http/h11_impl.py", line 396, in run_asgi result = await app(self.scope, self.receive, self.send) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/uvicorn/middleware/proxy_headers.py", line 45, in __call__ return await self.app(scope, receive, send) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/fastapi/applications.py", line 199, in __call__ await super().__call__(scope, receive, send) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/starlette/applications.py", line 111, in __call__ await self.middleware_stack(scope, receive, send) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/starlette/middleware/errors.py", line 181, in __call__ raise exc from None File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/starlette/middleware/errors.py", line 159, in __call__ await self.app(scope, receive, _send) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/starlette/exceptions.py", line 82, in __call__ raise exc from None File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/starlette/exceptions.py", line 71, in __call__ await self.app(scope, receive, sender) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/starlette/routing.py", line 566, in __call__ await route.handle(scope, receive, send) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/starlette/routing.py", line 227, in handle await self.app(scope, receive, send) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/starlette/routing.py", line 41, in app response = await func(request) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/fastapi/routing.py", line 195, in app dependency_overrides_provider=dependency_overrides_provider, File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/fastapi/dependencies/utils.py", line 550, in solve_dependencies solved = await run_in_threadpool(call, **sub_values) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/starlette/concurrency.py", line 34, in run_in_threadpool return await loop.run_in_executor(None, func, *args) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/concurrent/futures/thread.py", line 57, in run result = self.fn(*self.args, **self.kwargs) File "pydantic/main.py", line 400, in pydantic.main.BaseModel.__init__ pydantic.error_wrappers.ValidationError: 1 validation error for GetInput rank ValueError() takes no keyword arguments (type=type_error) ERROR:uvicorn.error:Exception in ASGI application Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/uvicorn/protocols/http/h11_impl.py", line 396, in run_asgi result = await app(self.scope, self.receive, self.send) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/uvicorn/middleware/proxy_headers.py", line 45, in __call__ return await self.app(scope, receive, send) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/fastapi/applications.py", line 199, in __call__ await super().__call__(scope, receive, send) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/starlette/applications.py", line 111, in __call__ await self.middleware_stack(scope, receive, send) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/starlette/middleware/errors.py", line 181, in __call__ raise exc from None File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/starlette/middleware/errors.py", line 159, in __call__ await self.app(scope, receive, _send) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/starlette/exceptions.py", line 82, in __call__ raise exc from None File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/starlette/exceptions.py", line 71, in __call__ await self.app(scope, receive, sender) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/starlette/routing.py", line 566, in __call__ await route.handle(scope, receive, send) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/starlette/routing.py", line 227, in handle await self.app(scope, receive, send) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/starlette/routing.py", line 41, in app response = await func(request) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/fastapi/routing.py", line 195, in app dependency_overrides_provider=dependency_overrides_provider, File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/fastapi/dependencies/utils.py", line 550, in solve_dependencies solved = await run_in_threadpool(call, **sub_values) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/starlette/concurrency.py", line 34, in run_in_threadpool return await loop.run_in_executor(None, func, *args) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/concurrent/futures/thread.py", line 57, in run result = self.fn(*self.args, **self.kwargs) File "pydantic/main.py", line 400, in pydantic.main.BaseModel.__init__ pydantic.error_wrappers.ValidationError: 1 validation error for GetInput rank ValueError() takes no keyword arguments (type=type_error)También revisé https://github.com/tiangolo/fastapi/issues/2180 .
Pero no pude encontrar una solución.
Lo que debo hacer es aumentar ValueError con un código de estado personalizado.
Nota: sé que puedo hacer el trabajo al generar HTTPException .
Pero estoy buscando una solución usando ValueError
¿Podría decirme dónde me estoy equivocando?
También he publicado este problema en Github - https://github.com/tiangolo/fastapi/issues/3761
Si no genera una HTTPException , normalmente cualquier otra excepción no detectada generará una respuesta 500 (un Internal Server Error ). Si su intención es responder con algún otro mensaje de error personalizado y estado HTTP al generar una excepción en particular, por ejemplo, ValueError , entonces puede agregar un controlador de excepción global a su aplicación:
from fastapi import FastAPI, Request from fastapi.responses import JSONResponse @app.exception_handler(ValueError) async def value_error_exception_handler(request: Request, exc: ValueError): return JSONResponse( status_code=400, content={"message": str(exc)}, )Esto le dará una respuesta 400 (o puede cambiar el código de estado a lo que quiera) como esta:
{ "message": "Value Must be within range (0,1000000)" }