英文:
fastapi: how to cache the value of fastapi dependency in a class-based (callable) dependency?
问题
这是您提供的代码的翻译部分:
# run.py
from functools import cache
import uvicorn
from fastapi import FastAPI, Depends
app = FastAPI()
class Dep:
def __init__(self, inp):
self.inp = inp
@cache
def __call__(self):
print(self.inp * 100)
return self.inp
@app.get("/a")
def a(v: str = Depends(Dep("a"))):
return v
@app.get("/a/a")
def aa(v: str = Depends(Dep("a"))):
return v
@app.get("/b")
def b(v: str = Depends(Dep("b"))):
return v
@app.get("/b/b")
def bb(v: str = Depends(Dep("b"))):
return v
def main():
uvicorn.run(
"run:app",
host="0.0.0.0",
reload=True,
port=8000,
workers=1
)
if __name__ == "__main__":
main()
此外,您提供了额外的信息和第二种方法的代码,但您没有明确提出问题,所以我只提供了主要代码的翻译。如果您有任何进一步的问题或需要其他翻译,请告诉我。
英文:
I have a small fastapi example here
# run.py
from functools import cache
import uvicorn
from fastapi import FastAPI, Depends
app = FastAPI()
class Dep:
def __init__(self, inp):
self.inp = inp
@cache
def __call__(self):
print(self.inp * 100)
return self.inp
@app.get("/a")
def a(v: str = Depends(Dep("a"))):
return v
@app.get("/a/a")
def aa(v: str = Depends(Dep("a"))):
return v
@app.get("/b")
def b(v: str = Depends(Dep("b"))):
return v
@app.get("/b/b")
def bb(v: str = Depends(Dep("b"))):
return v
def main():
uvicorn.run(
"run:app",
host="0.0.0.0",
reload=True,
port=8000,
workers=1
)
if __name__ == "__main__":
main()
I run python run.py
and the application spins up.
What I expect is that:
the first time I hit /a
or /a/a
endpoints it shows logs to me and print 100 "a" for me. the next times no logging happens because of the @cache
decorator
and
the first time I hit /b
or /b/b
endpoints it shows logs to me and print 100 "b"s for me. the next times no logging happens because of the @cache
decorator
What happens
The first time I hit /b
, it shows logs. the next times no log
The first time I hit /b/b
, it shows logs. the next times no log
The first time I hit /a
, it shows logs. the next times no log
The first time I hit /a/a
, it shows logs. the next times no log
the reason is that each time I am passing a value to the Dep class it is creating a new object and the call method is that of a new object each time. that is why the caching is not working properly.
and the caching is being done by fastapi dependency . That is why when I call an endpoint for the next times, I do not see new logs
But the question is how do I
- pass arguments to the callable dependency (a class)
- and also cache the value the function returns
Extra information
I tried to achieve the same using the approach below:
# run.py
from functools import cache
import uvicorn
from fastapi import FastAPI, Depends, Request
app = FastAPI()
@cache
def dep(inp):
@cache
def sub_dep():
print(inp*100)
return inp
return sub_dep
@app.get("/a")
def a(v: str = Depends(dep("a"))):
return v
@app.get("/a/a")
def aa(v: str = Depends(dep("a"))):
return v
@app.get("/b")
def b(v: str = Depends(dep("b"))):
return v
@app.get("/b/b")
def bb(v: str = Depends(dep("b"))):
return v
def main():
uvicorn.run(
"run:app",
host="0.0.0.0",
reload=True,
port=8000,
workers=1
)
if __name__ == "__main__":
main()
and it working as expected above
答案1
得分: 1
"The first time I hit /a, it shows logs. The next times, no log. The first time I hit /a/a, it shows logs. The next times, no log."
你第一次访问 /a 时,它会显示日志。接下来的访问,就不会有日志了。第一次我访问 /a/a 时,它也会显示日志。接下来的访问,仍然不会有日志。
You created four distinct objects at import
time when you defined those functions, a pair of "a" functions and a pair of "b" functions. There's no relationship among those four objects, they are all separate from one another. So a GET that uses one has no effect on the other three.
在 import
时,您创建了四个不同的对象,分别是一对 "a" 函数和一对 "b" 函数。这四个对象之间没有关联,它们彼此独立。因此,对其中一个对象的 GET 请求不会影响其他三个对象。
Consider creating a cached a_result()
helper function which both the /a and /a/a endpoints call. And similarly a b_result()
helper shared by both /b and /b/b. Now there is a linkage across endpoints.
考虑创建一个 cached 的 a_result()
辅助函数,同时被 /a 和 /a/a 端点调用。同样,也创建一个被 /b 和 /b/b 共享的 b_result()
辅助函数。现在,端点之间确实存在链接。
(If web clients can send an arbitrary arg to such a helper, then prefer lru_cache instead, so there's no memory leak.)
(如果 Web 客户端可以向这样的辅助函数发送任意参数,请使用 lru_cache ,以避免内存泄漏。)
英文:
> The first time I hit /a, it shows logs. The next times, no log. The first time I hit /a/a, it shows logs. The next times, no log.
You created four distinct objects at import
time
when you defined those functions, a pair of "a" functions and
a pair of "b" functions.
There's no relationship among those four objects,
they are all separate from one another.
So a GET that uses one has no effect on the other three.
Consider creating a
cached
a_result()
helper function which both the /a and /a/a endpoints call.
And similarly a b_result()
helper shared by both /b and /b/b.
Now there is a linkage across endpoints.
(If web clients can send an arbitrary arg to such a helper, then prefer
lru_cache
instead, so there's no memory leak.)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论