存储到磁盘-python-永久性备忘录

问题描述 投票:26回答:8

是否有一种方法可以将函数的输出记录到磁盘上?

我有功能

def getHtmlOfUrl(url):
    ... # expensive computation

并且想做类似的事情:

def getHtmlMemoized(url) = memoizeToFile(getHtmlOfUrl, "file.dat")

然后调用getHtmlMemoized(url),以便每个URL仅进行一次昂贵的计算。

python memoization
8个回答
27
投票

Python提供了一种非常优雅的方法-装饰器。基本上,装饰器是一个包装另一个功能以提供其他功能而不更改功能源代码的功能。您的装饰器可以这样写:

import json

def persist_to_file(file_name):

    def decorator(original_func):

        try:
            cache = json.load(open(file_name, 'r'))
        except (IOError, ValueError):
            cache = {}

        def new_func(param):
            if param not in cache:
                cache[param] = original_func(param)
                json.dump(cache, open(file_name, 'w'))
            return cache[param]

        return new_func

    return decorator

一旦掌握了这些,就可以使用@ -syntax'修饰'函数,您就可以使用了。

@persist_to_file('cache.dat')
def html_of_url(url):
    your function code...

请注意,此修饰器是有意简化的,可能不适用于所有情况,例如,当源函数接受或返回无法json序列化的数据时。

有关装饰的更多信息:How to make a chain of function decorators?

这是使装饰器在退出时仅保存一次缓存的方法:

import json, atexit

def persist_to_file(file_name):

    try:
        cache = json.load(open(file_name, 'r'))
    except (IOError, ValueError):
        cache = {}

    atexit.register(lambda: json.dump(cache, open(file_name, 'w')))

    def decorator(func):
        def new_func(param):
            if param not in cache:
                cache[param] = func(param)
            return cache[param]
        return new_func

    return decorator

20
投票

签出joblib.Memory。这是一个用于执行此操作的库。


4
投票

由Python的Shelve模块提供支持的更清洁的解决方案。优点是缓存可以通过众所周知的joblib.Memory语法进行实时更新,这也是异常证明(无需处理烦人的dict)。

KeyError

这将使函数仅被计算一次。下一个后续调用将返回存储的结果。


2
投票

import shelve def shelve_it(file_name): d = shelve.open(file_name) def decorator(func): def new_func(param): if param not in d: d[param] = func(param) return d[param] return new_func return decorator @shelve_it('cache.shelve') def expensive_funcion(param): pass 具有用于此的模块。 (您需要Artemis library

您装饰功能:

pip install artemis-ml

内部,它根据输入参数进行哈希运算,并通过该哈希值保存备忘录文件。


0
投票

这样的事情应该做:

from artemis.fileman.disk_memoize import memoize_to_disk

@memoize_to_disk
def fcn(a, b, c = None):
    results = ...
    return results

基本用法:

import json

class Memoize(object):
    def __init__(self, func):
        self.func = func
        self.memo = {}

    def load_memo(filename):
        with open(filename) as f:
            self.memo.update(json.load(f))

    def save_memo(filename):
        with open(filename, 'w') as f:
            json.dump(self.memo, f)

    def __call__(self, *args):
        if not args in self.memo:
            self.memo[args] = self.func(*args)
        return self.memo[args]

如果要在使用后将“” cache“写入文件,以后再加载:

your_mem_func = Memoize(your_func)
your_mem_func.load_memo('yourdata.json')
#  do your stuff with your_mem_func

0
投票

假设您的数据是json可序列化的,则此代码应该有效

your_mem_func.save_memo('yournewdata.json')

装饰import os, json def json_file(fname): def decorator(function): def wrapper(*args, **kwargs): if os.path.isfile(fname): with open(fname, 'r') as f: ret = json.load(f) else: with open(fname, 'w') as f: ret = function(*args, **kwargs) json.dump(ret, f) return ret return wrapper return decorator ,然后简单地调用它,如果它先前已运行过,您将获得缓存的数据。

已通过python 2.x和python 3.x检查


0
投票

还有getHtmlOfUrl

diskcache

-1
投票

您可以使用cache_to_disk软件包:

diskcache

这会将结果缓存3天,具体取决于参数a,b,c和d。结果存储在您计算机上的pickle文件中,并在下次调用该函数时被取消选中并返回。 3天后,将删除pickle文件,直到重新运行该功能。每当使用新参数调用该函数时,该函数将重新运行。此处更多信息:from diskcache import Cache cache = Cache("cachedir") @cache.memoize() def f(x, y): print('Running f({}, {})'.format(x, y)) return x, y

© www.soinside.com 2019 - 2024. All rights reserved.