lru 缓存在 Flask 应用程序上相同参数的应用程序运行之间不起作用
*编辑:刚刚意识到我在函数设计中犯了一个错误,在我的 Class1
函数中重新实例化了 AppDAO
,这就是导致意外行为的原因。我通过在 cache_call
中打印 self
参数来解决这个问题。
我有一个具有以下设计的 Flask 应用程序:
from flask import Flask, request
from Class1 import Class1
from AppDAO import AppDAO
app = Flask(__name__)
def main():
app.config['appDAO'] = AppDAO()
app.run()
@app.route('/app_route1',methods=['POST'])
def app_route1():
print("Running app route 1...")
print(app.config['appDAO'].cache_call.cache_info())
cache_param = request.json.get('cached_parameter')
print("The cached parameter is: %s." % cache_param)
class1 = Class1(app.config['appDAO'])
for item in ['item1', 'item2']:
class1.do_processing(item,cache_param)
Class1.py
:
class Class1(object):
def __init__(self, app_dao):
self.app_dao = app_dao
def do_processing(self, item, cache_param):
print("Processing for item: %s..." % item)
resp_cache = self.app_dao.cache_call(cache_param)
print(self.app_dao.cache_call.cache_info())
return resp_cache
AppDAO.py
:
from functools import lru_cache
import mysql.connector
class AppDAO(object):
def __init__():
self.conn = mysql.connector.connect('user1','password1','server1','database')
@lru_cache(maxsize=4)
def cache_call(self, cache_param):
print("Running cache call with parameter: %s..." % cache_param)
cursor = self.conn.cursor()
cursor.execute("SELECT * FROM Table1 WHERE Column1 = `%s`;" % cache_param)
rs = cursor.fetchall()
return rs
如果我运行发布帖子的应用程序,AppDAO.cache_call 使用以下输出
print
输出正确运行:
Running app route 1...
CacheInfo(hits=0, misses=0, maxsize=4, currsize=0)
Processing items: item1...
Running cache call with parameter: foo1...
CacheInfo(hits=0, misses=1, maxsize=4, currsize=1)
Processing items: item2...
CacheInfo(hits=1, misses=1, maxsize=4, currsize=1)
但是我使用 cache_call
的相同参数向分支发出另一张帖子,我得到以下 print< /code> 输出:
Running app route 1...
CacheInfo(hits=1, misses=1, maxsize=4, currsize=1)
Processing items: item1...
Running cache call with parameter: foo1...
CacheInfo(hits=1, misses=2, maxsize=4, currsize=2)
Processing items: item2...
CacheInfo(hits=2, misses=2, maxsize=4, currsize=2)
我使用以下命令运行应用程序Anaconda QT Console
,但如果我也使用 Anaconda Command Prompt
,我会遇到以下缓存问题。任何人都可以推测为什么当向应用程序发出新帖子时,尽管缓存的调用仍在清除中,但 lru_cache
不起作用?
*Edit: just realized I made a mistake in my function design where I re-instantiated the AppDAO
in my Class1
function and that is what was causing the unexpected behavior. I figured it out by printing the self
argument in cache_call
.
I have a Flask App with the following design:
from flask import Flask, request
from Class1 import Class1
from AppDAO import AppDAO
app = Flask(__name__)
def main():
app.config['appDAO'] = AppDAO()
app.run()
@app.route('/app_route1',methods=['POST'])
def app_route1():
print("Running app route 1...")
print(app.config['appDAO'].cache_call.cache_info())
cache_param = request.json.get('cached_parameter')
print("The cached parameter is: %s." % cache_param)
class1 = Class1(app.config['appDAO'])
for item in ['item1', 'item2']:
class1.do_processing(item,cache_param)
Class1.py
:
class Class1(object):
def __init__(self, app_dao):
self.app_dao = app_dao
def do_processing(self, item, cache_param):
print("Processing for item: %s..." % item)
resp_cache = self.app_dao.cache_call(cache_param)
print(self.app_dao.cache_call.cache_info())
return resp_cache
AppDAO.py
:
from functools import lru_cache
import mysql.connector
class AppDAO(object):
def __init__():
self.conn = mysql.connector.connect('user1','password1','server1','database')
@lru_cache(maxsize=4)
def cache_call(self, cache_param):
print("Running cache call with parameter: %s..." % cache_param)
cursor = self.conn.cursor()
cursor.execute("SELECT * FROM Table1 WHERE Column1 = `%s`;" % cache_param)
rs = cursor.fetchall()
return rs
If I run the app making a post, the AppDAO.cache_call
functions correctly with the following output print
output:
Running app route 1...
CacheInfo(hits=0, misses=0, maxsize=4, currsize=0)
Processing items: item1...
Running cache call with parameter: foo1...
CacheInfo(hits=0, misses=1, maxsize=4, currsize=1)
Processing items: item2...
CacheInfo(hits=1, misses=1, maxsize=4, currsize=1)
But I make another post to the branch using the same parameter for the cache_call
, I get the following print
output:
Running app route 1...
CacheInfo(hits=1, misses=1, maxsize=4, currsize=1)
Processing items: item1...
Running cache call with parameter: foo1...
CacheInfo(hits=1, misses=2, maxsize=4, currsize=2)
Processing items: item2...
CacheInfo(hits=2, misses=2, maxsize=4, currsize=2)
I run the app using the Anaconda QT Console
, but I experience the following caching issue if I used an Anaconda Command Prompt
as well. Can anyone speculate why the lru_cache
is not working when a new post is made to the app despite the cached call still clearing being stored?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
请注意,这
是包装一个方法,而不是一个函数。在您的示例中,将用作缓存键的一部分的
self
是Class1
的实例,并且在每次路由处理程序调用时创建一次。结果是您没有获得预期的缓存。更新:我误读了代码。假设这
是一个拼写错误,而且应该是这样
,并且您
do_processing
故意不将item
(具体情况有所不同)传递给cache_call
,那么会发生什么您看到的与lru_cache
的行为方式一致。在第一个请求时,它将向缓存添加一个内容 (
request.json.get('cached_parameter')
),将其评分为“item1”未命中和“item2”命中。在第二个请求中,
request.json.get('cached_parameter')
是一个不同的对象。添加了“item1”,将其评分为未命中(将“currsize”增加到 2)。对于“item2”,它被计为命中。您期望什么行为?
不相关但值得一提:构建查询的方式使您容易受到 SQL 注入攻击。考虑改用绑定参数。
Note that
is wrapping a method, not a function. In your example,
self
, which will be used as as part of the cache key, is an instance ofClass1
and is created once per route handler invocation. The result is that you aren't getting the caching you expect.Updated: I misread the code. Assuming that
was a typo, and should be
and that you're
do_processing
is intentionally not passingitem
(which varies) tocache_call
, then what you're seeing is consistent with howlru_cache
behaves.On first request, it's going to add one thing (
request.json.get('cached_parameter')
) to the cache, scoring it as a miss the for 'item1' and a hit for 'item2'.On second request,
request.json.get('cached_parameter')
is a different object. It gets scored as a miss for 'item1', added (increasing 'currsize' to 2). For 'item2', it gets scored as a hit.What behavior did you expect?
Unrelated but worth mentioning: The way you're constructing that query leaves you open to SQL Injection attacks. Consider using a bind parameter instead.