lru缓存在Flask App上的相同参数的应用程序运行之间不起作用
lru caching not working between application runs for same argument on Flask App
*编辑:刚刚意识到我在函数设计中犯了一个错误,我在我的 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
如果我 运行 应用程序制作 post,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
相同的参数向分支创建另一个 post,我得到以下 print
输出:
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
在对应用程序进行新的 post 时不起作用,尽管缓存的调用仍在清除存储中?
注意
@lru_cache(maxsize=4)
def cache_call(self, cache_param):
正在包装一个方法,而不是一个函数。在您的示例中,self
将用作缓存键的一部分,它是 Class1
的一个实例,并且在每次路由处理程序调用时创建一次。结果是您没有获得预期的缓存。
更新:我看错了代码。假设
for item in [item1, item2]:
打错了,应该是
for item in ['item1', 'item2']:
并且您 do_processing
有意不将 item
(有所不同)传递给 cache_call
,那么您所看到的与 lru_cache
的方式一致行为举止。
在第一次请求时,它会向缓存中添加一个东西 (request.json.get('cached_parameter')
),将其计为 'item1' 未命中和 'item2' 命中。
在第二次请求时,request.json.get('cached_parameter')
是一个不同的对象。它被计为 'item1' 未命中,已添加(将 'currsize' 增加到 2)。对于 'item2',它被计为命中。
您期望什么行为?
不相关但值得一提:构建该查询的方式使您容易受到 SQL 注入攻击。考虑改用绑定参数。
*编辑:刚刚意识到我在函数设计中犯了一个错误,我在我的 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
如果我 运行 应用程序制作 post,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
相同的参数向分支创建另一个 post,我得到以下 print
输出:
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
在对应用程序进行新的 post 时不起作用,尽管缓存的调用仍在清除存储中?
注意
@lru_cache(maxsize=4)
def cache_call(self, cache_param):
正在包装一个方法,而不是一个函数。在您的示例中,self
将用作缓存键的一部分,它是 Class1
的一个实例,并且在每次路由处理程序调用时创建一次。结果是您没有获得预期的缓存。
更新:我看错了代码。假设
for item in [item1, item2]:
打错了,应该是
for item in ['item1', 'item2']:
并且您 do_processing
有意不将 item
(有所不同)传递给 cache_call
,那么您所看到的与 lru_cache
的方式一致行为举止。
在第一次请求时,它会向缓存中添加一个东西 (request.json.get('cached_parameter')
),将其计为 'item1' 未命中和 'item2' 命中。
在第二次请求时,request.json.get('cached_parameter')
是一个不同的对象。它被计为 'item1' 未命中,已添加(将 'currsize' 增加到 2)。对于 'item2',它被计为命中。
您期望什么行为?
不相关但值得一提:构建该查询的方式使您容易受到 SQL 注入攻击。考虑改用绑定参数。