用python实现一个缓存机制

学习一下关于wukong-robot的声音文件缓存机制

使用缓存的目的

由于使用的是在线语音合成,每一次对话都要访问网络合成语音。为了尽量减少访问网络的次数,可以对一些可以反复使用的语音进行缓存。

设计思路

在speak()函数中添加一个 布尔类型的 “cache” 参数作为是否要启用缓存的标志。当传入为True时,首先使用 get_cache(msg)尝试命中缓存,若未命中,就调用 save_cache(voice, msg)将这句缓存下来。

speak
1
2
3
4
5
6
7
8
9
10
11
voice = ''
if utils.get_cache(msg):
logger.info("命中缓存,播放缓存语音")
voice = utils.get_cache(msg)
else:
try:
voice = self.tts.get_speech(msg)
if cache:
utils.save_cache(voice, msg)
except Exception as e:
logger.error('保存缓存失败:{}'.format(e))

save_cache(voice, msg)

描述:

  1. 获取voice文件的后缀名,并将msg散列化为十六进制字符串
  2. 将voice文件存放到项目的temp文件夹中,文件名为msg的16进制哈希值+voice的后缀

为什么要使用MD5命名文件?

  1. 生成的摘要长度固定:msg的长度是不确定的,但是文件名的长度却能固定
  2. 可以验证一致性:每一个msg都有固定的散列值
utils.py
1
2
3
4
5
def saveCache(voice, msg):
""" 获取缓存的语音 """
foo, ext = os.path.splitext(voice)
md5 = hashlib.md5(msg.encode('utf-8')).hexdigest()
shutil.copyfile(voice, os.path.join(constants.TEMP_PATH, md5+ext))

get_cache(msg)

描述:

  1. 获取msg的md5哈希值
  2. 将哈希值与其他部分合成路径
  3. 若路径所指的文件是存在的,那么返回路径,不然返回None
1
2
3
4
5
6
7
8
9
10
def getCache(msg):
""" 获取缓存的语音 """
md5 = hashlib.md5(msg.encode('utf-8')).hexdigest()
mp3_cache = os.path.join(constants.TEMP_PATH, md5 + '.mp3')
wav_cache = os.path.join(constants.TEMP_PATH, md5 + '.wav')
if os.path.exists(mp3_cache):
return mp3_cache
elif os.path.exists(wav_cache):
return wav_cache
return None

延伸

这个缓存的机制简明易懂,如果其他项目也需要一个缓存系统,我想主要就是要想好:

  1. 缓存文件怎么存什么时候存?
  2. 缓存文件怎么找什么时候找?

以上

鼓励一下:D