当前位置:嗨网首页>书籍在线阅读

05- 实现磁盘缓存

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

[toc]

3.3.1 实现磁盘缓存

上一节中,我们介绍了创建基于磁盘的缓存时需要考虑的文件系统限制,包括允许使用哪些字符、文件名长度限制,以及确保文件和目录的创建位置不同。把URL到文件名的这些映射逻辑与代码结合起来,就形成了磁盘缓存的主要部分。下面是 DiskCache 类的初始实现代码。

import os
import re
from urllib.parse import urlsplit
class DiskCache:
    def __init__(self, cache_dir='cache', max_len=255):
        self.cache_dir = cache_dir
        self.max_len = max_len
    def url_to_path(self, url):
        """ Return file system path string for given URL"""
        components = urlsplit(url)
        # append index.html to empty paths
        path = components.path
        if not path:
            path = '/index.html'
        elif path.endswith('/'):
            path += 'index.html'
        filename = components.netloc + path + components.query
        # replace invalid characters
        filename = re.sub('[^/0-9a-zA-Z\-.,;_ ]', '_', filename)
        # restrict maximum number of characters
        filename = '/'.join(seg[:self.max_len] for seg in
filename.split('/'))
        return os.path.join(self.cache_dir, filename)

在上面的代码中,构造方法传入了一个用于设定缓存位置的参数,然后在 url_to_path 方法中应用了前面讨论的文件名限制。现在,我们还缺少根据文件名存取数据的方法。

下面的代码实现了这两个缺失的方法。

import json
class DiskCache:
    ...
    def __getitem__(self, url):
        """Load data from disk for given URL"""
        path = self.url_to_path(url)
        if os.path.exists(path):
            return json.load(path)
        else:
            # URL has not yet been cached
            raise KeyError(url + ' does not exist')
    def __setitem__(self, url, result):
        """Save data to disk for given url"""
        path = self.url_to_path(url)
        folder = os.path.dirname(path)
        if not os.path.exists(folder):
            os.makedirs(folder)
        json.dump(result, path)

__setitem()__ 中,我们使用 url_to_path() 方法将URL映射为安全文件名,在必要情况下还需要创建父目录。这里使用的 json 模块会对Python进行序列化处理,然后保存到磁盘中。而在 __getitem__() 方法中,首先会将URL映射为安全文件名。如果文件存在,则使用 json 加载其内容,并恢复其原始数据类型;如果文件不存在(即缓存中还没有该URL的数据),则会抛出 KeyError 异常。