Python 创建在执行之间保持的内存缓存

Python 创建在执行之间保持的内存缓存,python,caching,command-line,os-agnostic,Python,Caching,Command Line,Os Agnostic,我正在开发一个Python命令行实用程序,它可能涉及对一组文件的相当大的查询。这是一个相当有限的查询列表(想想索引的DB列)来提高性能,在这个过程中,我可以生成一次排序/结构化列表、映射和树,并重复地命中它们,而不是每次命中文件系统 但是,这些缓存在进程结束时丢失,每次脚本运行时都需要重建,这大大增加了程序的运行时间。我想确定在我的命令的多个执行之间共享这些数据的最佳方式,这些执行可能是并发的、一个接一个的,或者在执行之间有明显的延迟 要求: 必须快速-任何类型的每次执行处理都应该最小化,这包

我正在开发一个Python命令行实用程序,它可能涉及对一组文件的相当大的查询。这是一个相当有限的查询列表(想想索引的DB列)来提高性能,在这个过程中,我可以生成一次排序/结构化列表、映射和树,并重复地命中它们,而不是每次命中文件系统

但是,这些缓存在进程结束时丢失,每次脚本运行时都需要重建,这大大增加了程序的运行时间。我想确定在我的命令的多个执行之间共享这些数据的最佳方式,这些执行可能是并发的、一个接一个的,或者在执行之间有明显的延迟

要求:

  • 必须快速-任何类型的每次执行处理都应该最小化,这包括磁盘IO和对象构造
  • 必须是操作系统无关的(或者至少能够在Unix/Windows上钩住类似的底层行为,这更可能)
  • 必须允许相当复杂的查询/筛选-我认为键/值映射不够好
  • 需要是最新的吗?(简单地说)陈旧的数据很好,这只是一个缓存,实际的数据正在分别写入磁盘
  • 不能使用重量级的守护进程,比如MySQL或MemCached——我想尽量减少安装成本,要求每个用户安装这些服务太多了
首选项:

  • 我希望尽可能避免任何长时间运行的守护进程
  • 虽然我希望能够快速更新缓存,但在更新时重建整个缓存并不是世界末日,快速读取比快速写入重要得多
在我理想的幻想世界中,我能够在执行之间直接保留Python对象,有点像Java线程(比如Tomcat请求)共享单例数据存储对象,但我意识到这可能是不可能的。不过,我越接近这一点越好

候选人:

  • 内存中的SQLite

    对于我的用例来说,SQLite本身似乎不够快,因为它是由磁盘支持的,因此每次执行时都必须从文件中读取。也许这并不像看上去的那么糟糕,但似乎有必要将数据库持久存储在内存中。SQLite允许DBs访问,但这些DBs在程序退出时被销毁,并且不能在实例之间共享

  • 使用将平面文件数据库加载到内存中

    另一方面,我可以将缓存写入磁盘,然后使用mmap将它们加载到内存中,在不同的执行之间可以共享相同的内存空间。但是,我不清楚如果所有进程都退出,mmap会发生什么。如果mmap最终从内存中刷新,这没关系,但我希望它能保留一点(30秒?几分钟?),这样用户就可以一个接一个地运行命令,并且缓存可以重用。似乎暗示需要有一个打开的mmap句柄,但我还没有找到内存映射文件从内存中删除并需要从磁盘重新加载的确切描述

    我想我可以实现这个,如果mmap对象在退出后仍然存在,但感觉级别非常低,我想有人已经实现了一个更优雅的解决方案。我不想在开始构建它时才意识到我一直在重建SQLite。另一方面,它感觉会非常快,并且我可以根据我的特定用例进行优化

  • 使用Processing在进程之间共享Python对象

    处理包指示“”。通过查看其余的文档,我没有看到进一步提到这种行为,但这听起来很有希望。有人能告诉我更多的信息吗

  • 将数据存储在RAM磁盘上

    我在这里关心的是操作系统的特定功能,但我可以,然后简单地按照我的意愿读/写它(SQLite?)。该软件包似乎是一个有前途的替代方案,可以与多个操作系统一起工作,但评论中暗示了相当多的限制

我知道这是一种存储Python对象的有效方法,因此它可能比任何类型的手动数据存储都具有速度优势。我可以把pickle挂到上面的选项中吗?这会比平面文件或SQLite更好吗

我知道有很多与此相关的问题,但我做了大量的挖掘,没有找到任何直接解决我关于多个命令行执行的问题的方法

我完全承认,我可能想得太多了。我只是想了解我的选择,以及它们是否值得。


非常感谢你的帮助

我只想。。。在您的情况下,很可能只是转储到pickle文件。如果您发现速度不够快,请尝试更复杂的方法(如memcached或SQLite)。Donald Knuth说“过早优化是万恶之源”

我不会很快得出这样的结论:“SQLite本身对于我的用例来说似乎不够快,因为它是由磁盘支持的,因此每次执行时都必须从文件中读取数据。”您只有在尝试时才知道它是否足够快。此外,操作系统无论如何都会进行缓存。Redis或Memcached也可能是解决方案。为什么不使用长时间运行的进程呢?这个用例正是Redis和Memcached所解决的,还有一个额外的优点,就是您可以在自己的程序重新启动时保持缓存。如果您需要在key/val之外进行查询,那么pickle将如何成为候选,除非您正在pickle自己的自定义查询启用类?此外,pickle不是共享内存的好解决方案,除非在文件访问周围添加锁定。您是否需要在多个进程之间共享内存,或者这仅适用于单个进程?Pickle如果他们是一个