Python 中的持久记忆

2023-12-27

我有一个昂贵的函数,它接受并返回少量数据(一些整数和浮点数)。我已经memoized http://en.wikipedia.org/wiki/Memoization这个功能,但我想让备忘录持久化。已经有几个与此相关的线程,但我不确定某些建议方法的潜在问题,并且我有一些相当具体的要求:

  • 我肯定会同时使用多个线程和进程的函数(都使用multiprocessing以及来自单独的 python 脚本)
  • 我不需要从这个 python 函数外部读取或写入备忘录
  • 我并不担心备忘录在极少数情况下会被损坏(例如拔掉插头或意外写入文件而不锁定它),因为它不是that重建成本高昂(通常需要 10-20 分钟),但我希望它不会因为异常而损坏,或者手动终止 python 进程(我不知道这有多现实)
  • 我强烈喜欢不需要大型外部库的解决方案,因为我将在一台机器上运行代码,其硬盘空间非常有限
  • 我对跨平台代码的偏好较弱,但我可能只会在 Linux 上使用它

这个线程 https://stackoverflow.com/questions/486490/python-shelve-module-question讨论了shelve模块,这显然不是进程安全的。其中两个答案建议使用fcntl.flock锁定搁置文件。中的一些回复这个线程 https://stackoverflow.com/questions/489861/locking-a-file-in-python然而,似乎表明这充满了问题 - 但我不太确定它们是什么。听起来好像这仅限于 Unix(尽管显然 Windows 有一个等效的称为msvcrt.locking),并且锁定只是“建议” - 即,它不会阻止我在不检查文件是否已锁定的情况下意外写入文件。还有其他潜在的问题吗?写入文件的副本并作为最后一步替换主副本是否可以降低损坏的风险?

看起来不像数据库模块 http://docs.python.org/py3k/library/dbm.html会比搁置更好。我快速浏览了一下sqlite3 http://docs.python.org/library/sqlite3.html,但为了这个目的似乎有点矫枉过正。这个线程 https://stackoverflow.com/questions/1235594/comparing-persistent-storage-solutions-in-python and this one https://stackoverflow.com/questions/8428103/is-there-an-established-memoize-on-disk-decorator-for-python提到几个第三方库,包括ZODB http://www.zodb.org/index.html,但是有很多选择,对于这个任务来说,它们都显得过于庞大和复杂。

有人有建议吗?

UPDATE:下面提到了 IncPy,它看起来确实很有趣。不幸的是,我不想回到Python 2.6(我实际上使用的是3.2),而且看起来与C库一起使用有点尴尬(我大量使用numpy和scipy等)。

kindall 的另一个想法很有启发性,但我认为将其适应多个进程会有点困难 - 我认为用文件锁定或数据库替换队列是最简单的。

再次查看 ZODB,它看起来确实非常适合该任务,但我确实想避免使用任何其他库。我仍然不完全确定简单使用会出现什么问题flock是 - 我想一个大问题是进程是否在写入文件时或释放锁之前终止?

所以,我采纳了synthesizerpatel的建议并选择了sqlite3。如果有人感兴趣,我决定做一个直接替代品dict它将其条目作为泡菜存储在数据库中(我不需要在内存中保留任何内容,因为数据库访问和泡菜与我正在做的其他事情相比已经足够快了)。我确信有更有效的方法可以做到这一点(并且我不知道我是否仍然存在并发问题),但这里是代码:

from collections import MutableMapping
import sqlite3
import pickle


class PersistentDict(MutableMapping):
    def __init__(self, dbpath, iterable=None, **kwargs):
        self.dbpath = dbpath
        with self.get_connection() as connection:
            cursor = connection.cursor()
            cursor.execute(
                'create table if not exists memo '
                '(key blob primary key not null, value blob not null)'
            )
        if iterable is not None:
            self.update(iterable)
        self.update(kwargs)

    def encode(self, obj):
        return pickle.dumps(obj)

    def decode(self, blob):
        return pickle.loads(blob)

    def get_connection(self):
        return sqlite3.connect(self.dbpath)

    def  __getitem__(self, key):
        key = self.encode(key)
        with self.get_connection() as connection:
            cursor = connection.cursor()
            cursor.execute(
                'select value from memo where key=?',
                (key,)
            )
            value = cursor.fetchone()
        if value is None:
            raise KeyError(key)
        return self.decode(value[0])

    def __setitem__(self, key, value):
        key = self.encode(key)
        value = self.encode(value)
        with self.get_connection() as connection:
            cursor = connection.cursor()
            cursor.execute(
                'insert or replace into memo values (?, ?)',
                (key, value)
            )

    def __delitem__(self, key):
        key = self.encode(key)
        with self.get_connection() as connection:
            cursor = connection.cursor()
            cursor.execute(
                'select count(*) from memo where key=?',
                (key,)
            )
            if cursor.fetchone()[0] == 0:
                raise KeyError(key)
            cursor.execute(
                'delete from memo where key=?',
                (key,)
            )

    def __iter__(self):
        with self.get_connection() as connection:
            cursor = connection.cursor()
            cursor.execute(
                'select key from memo'
            )
            records = cursor.fetchall()
        for r in records:
            yield self.decode(r[0])

    def __len__(self):
        with self.get_connection() as connection:
            cursor = connection.cursor()
            cursor.execute(
                'select count(*) from memo'
            )
            return cursor.fetchone()[0]

sqlite3 开箱即用提供ACID http://en.wikipedia.org/wiki/ACID。文件锁定很容易出现竞争条件和并发问题,而使用 sqlite3 则不会出现这些问题。

基本上,是的,sqlite3 超出了您的需要,但它并不是一个巨大的负担。它可以在手机上运行,​​所以这并不像你承诺运行一些糟糕的软件。它将节省您重新发明轮子和调试锁定问题的时间。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python 中的持久记忆 的相关文章

随机推荐

  • 有没有javascript的统计库? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我需要在 javascript 上实现一些统计测试 例如 T 测试 Anova 和 Wilcoxon 与
  • URI.unescape 在尝试将“%C3%9Fą”转换为“ßą”时崩溃

    我在用URI unescape http ruby doc org stdlib 1 9 3 libdoc uri rdoc URI Escape html method i unescape要取消转义文本 不幸的是我遇到了奇怪的错误 en
  • Keycloak - 多重/2FA 因素 - OTP - 二维码 - 自定义登录屏幕 - Rest API

    I have 我自己的登录页面 用户在其中输入用户名 密码 该用户名 密码用于通过 Keycloak Rest API 登录 http localhost 8080 auth realms Demo protocol openid conn
  • SQL代理作业:确定它已经运行了多长时间

    场景 某些 SQL 代理作业计划全天每隔几分钟运行一次 在某些情况下 它会错过下一个时间表 因为它仍在按照上一个时间表运行 有时 工作可能会 挂起 这不会产生失败 因为作业尚未停止 发生这种情况时 可以手动停止该作业 并在下次运行时正常工作
  • React 如何在调用 onSubmit 时绑定到组件

    在我的组件中 我尝试调用组件的handleChange 和handleSubmit 函数 如果我像这样渲染表格示例 https facebook github io react docs forms html
  • JQuery如何从href标签中提取值?

    我是 JQuery 新手 如果我有以下标签 最好的 JQuery 方法是什么 从 href 中提取 page 的值 a href Search Advanced page 2 2 a Malcolm 我首先想到的是单行正则表达式 var p
  • 如何为来自同一链接的页面添加规范标签?

    我正在使用 symfony 1 0 6 在我的网站中 我有两个 URL http newe4s com news articles view 033 job news and information and http newe4s com
  • 从 DropdownButtonFormField 中删除下划线

    如何从 DropdownButtonFormField 中删除下划线 检查下面的照片 我尝试了 InputDecortaion 的各种选项组合 但找不到任何方法 SizedBox width 100 0 child DropdownButt
  • get/set 已被弃用,取而代之的是 config 命令

    在命令行中使用 angular cli 我执行了 ng set defaults styleExt styl 将默认样式设置为 Stylus 我得到了以下响应 get set 已被弃用 取而代之的是 config 命令 我想更改现有项目的样
  • Prolog递归过程解释

    如果可能的话 我希望有人解释这个过程 来自 立即学习序言 一书 它需要两个数字并将它们加在一起 add 0 Y Y add s X Y s Z add X Y Z 原则上我明白 但我有一些问题 假设我发出查询 add s s 0 s 0 R
  • 寻找一种有效的方法或算法来检查文件是否属于某个文件夹路径列表中的某个项目

    我有一个文件夹路径列表 此列表中可能有许多 数十个甚至数百个文件夹路径 例如 C Program Files 7 Zip many directories under C Program Files C ProgramData Adobe
  • 通过 microsoft webtest 上传文件

    我有一个 webtest 我打算用它来加载测试将文件上传到网站 我正在使用 Visual Studio 中内置的 WebTest 框架 目的是从 Azure 运行更大规模的测试 我创建了一个新的网络测试并记录了步骤 包括文件上传 这一切都记
  • 在哪里可以找到特定 Git 提交的快照?

    我了解到 Git 为每次提交保留一个快照 快照本质上是copies of changed文件和一些references to unchanged files 所有Git相关数据都存储在 git存储库目录内的目录 duong2179 mbpr
  • weakhashmap是如何工作的? [复制]

    这个问题在这里已经有答案了 就像weakhashmap如何理解对其键之一的引用现在已经过时一样 尤其是如果键是池化的字符串的话 您不能将字符串文字与 WeakHashMap 一起使用 当然可以 但这样做没有意义 String myKey s
  • 如何在 Swift 中的泛型扩展中使用带有可选类方法的协议?

    我正在尝试使用类方法对现有类进行扩展 例如 objc public protocol MyProtocol optional class func foo gt Int 我在扩展中使用这个协议 通用如下 extension MyClass
  • 如果会话超时,MVC 中的 jquery ajax 调用后如何重定向到新页面?

    1 我有一个调用操作的Ajax链接 该操作返回一个视图 该视图在特定的Div中打开 将其视为使用相应视图更新div的菜单 2 如果会话超时 则返回我的登录视图 因此 如果我单击链接并且会话超时 登录视图将在 div 中打开 而不是在整个页面
  • 每天执行一次查询

    基本上我有一个MySQL数据库 其中有一个表存储我网站用户的请求 我想自动执行一个查询 删除所有已完成的请求 已完成意味着该列Status 3 根据该列 超过 180 天ArchivingDate My Requests table Req
  • 六个月内保留的参与者百分比

    我是一名学校老师 对 MS SQL Server 非常陌生 每个人都建议尝试一下这个网站 开始 我正在尝试编写查询来测试参与学术项目的不同类型的结果衡量标准 我想尝试几种不同的方法来计算这个结果测量 我试图计算的结果是 在该计划的六个月内保
  • 如何在不同的计算机上克隆 RStudio 环境

    我最近一直在加快使用 R 的速度 并且想知道最有效的方法是将 RStudio 环境 尤其是软件包安装 从一台计算机克隆到另一台计算机 我希望能够从台式机切换到笔记本电脑 但我在工作时经常向台式机添加软件包 并且希望有一种简单的方法来确保在笔
  • Python 中的持久记忆

    我有一个昂贵的函数 它接受并返回少量数据 一些整数和浮点数 我已经memoized http en wikipedia org wiki Memoization这个功能 但我想让备忘录持久化 已经有几个与此相关的线程 但我不确定某些建议方法