Jupyter(Python)中无法使用Cache原理分析
前言
最近需要在Jupyter中写一个类库,其中有一个文件实现从数据库中读取空间数据并加载为Feature对象,Feature对象是cartopy封装的geometry列表,能够方便的用于作图等。因为有很多数据是经常用到的,所以就写了很多常量将数据事先读好供用户直接调用,这样造成的一个问题是每次加载该页面的时候很慢,于是我就考虑可以写个Cache来缓存这些数据,这在其他情况下是再正常不过的需求,然而我却在这里折腾半天,踏了坑,坑里还有水,再也没有出来。。。在这里我简单分析一下失败的原因,如果有人有能解决的方案或者我有什么说的不对的地方,欢迎批评指导!
折腾过程
首先我考虑这个应该是写个Cache类,其中加入一个字典,于是找到了这样一块代码,初步看了一下代码没有问题,于是Copy上:
#coding=utf-8
from time import time
class Cache:
'''简单的缓存系统'''
def __init__(self):
'''初始化'''
self.mem = {}
self.time = {}
def set(self, key, data, age=-1):
'''保存键为key的值,时间位age'''
self.mem[key] = data
if age == -1:
self.time[key] = -1
else:
self.time[key] = time() + age
return True
def get(self,key):
'''获取键key对应的值'''
if key in self.mem.keys():
if self.time[key] == -1 or self.time[key] > time():
return self.mem[key]
else:
self.delete(key)
return None
else:
return None
def delete(self,key):
'''删除键为key的条目'''
del self.mem[key]
del self.time[key]
return True
def clear(self):
'''清空所有缓存'''
self.mem.clear()
self.time.clear()
很清晰的一段代码,并且加入了缓存时间,应当能满足我的要求的,在此页面定义了一个变量,创建一个FEATURE_CACHE对象如下:
FEATURE_CACHE = Cache()
这样我在需要缓存的页面只要先判断是否在缓存内,是则直接读取,否则使用原来的逻辑读取数据库并存入缓存即可,改造如下:
if FEATURE_CACHE.get(ds_id) != None:
return FEATURE_CACHE.get(ds_id)
else:
geo_feature = ...
FEATURE_CACHE.set(ds_id, geo_feature)
return geo_feature
逻辑上清晰易懂,然后尝试调用。新建一个jupyter页面,多次调用,很好,只有第一次比较慢,再次调用就非常快,本以为这就解决了问题,我也是灵光一闪,既然我是全局缓存那就再开一个页面试试吧,于是又新建了一个jupyter页面,大跌眼镜的事情出现了,居然也是第一次调用非常慢,这是什么逻辑,为什么这里面没有缓存。然后经历了无数次加输出信息调试、重启kernel调试、staticmethod方法、单例等均达不到效果,单例的代码如下:
class Cache:
__instance = None
__lock = threading.Lock() # used to synchronize code
mem = {}
time = {}
def __init__(self):
"disable the __init__ method"
'''简单的缓存系统'''
def set(self, key, data, age=-1):
'''保存键为key的值,时间位age'''
self.mem[key] = data
if age == -1:
self.time[key] = -1
else:
self.time[key] = time() + age
return True
def get(self,key):
'''获取键key对应的值'''
if key in self.mem.keys():
if self.time[key] == -1 or self.time[key] > time():
return self.mem[key]
else:
self.delete(key)
return None
else:
return None
def delete(self,key):
'''删除键为key的条目'''
del self.mem[key]
del self.time[key]
return True
def clear(self):
'''清空所有缓存'''
self.mem.clear()
self.time.clear()
@staticmethod
def getInstance():
if not Cache.__instance: