如果我在python中有一个可能超出可用内存地址空间的列表(或数组,字典......),(32位python)有哪些选项和相对速度?(除了不列出那么大的列表)该列表可能会超出内存,但我无法事先知道。一旦它开始超过 75%,我不想再将列表保留在内存中(或者无论如何都是新项目),有没有办法在中途转换为基于文件的方法?
最好的(进出速度)文件存储选项是什么?
只需要存储一个简单的数字列表。无需随机访问第 N 个元素,只需追加/弹出类型的操作。
如果我在python中有一个可能超出可用内存地址空间的列表(或数组,字典......),(32位python)有哪些选项和相对速度?(除了不列出那么大的列表)该列表可能会超出内存,但我无法事先知道。一旦它开始超过 75%,我不想再将列表保留在内存中(或者无论如何都是新项目),有没有办法在中途转换为基于文件的方法?
最好的(进出速度)文件存储选项是什么?
只需要存储一个简单的数字列表。无需随机访问第 N 个元素,只需追加/弹出类型的操作。
如果您的“数字”足够简单(每个最多 4 个字节的有符号或无符号整数,或每个 4 或 8 个字节的浮点数),我推荐标准库数组模块作为保留数百万个它们的最佳方式在内存中(你的“虚拟数组”的“尖端”)有一个二进制文件(为二进制 R/W 打开)支持磁盘上的其余结构。 array.array
具有非常快速fromfile
和tofile
方法来促进数据来回移动。
即,基本上,假设例如无符号长数字,例如:
import os
# no more than 100 million items in memory at a time
MAXINMEM = int(1e8)
class bigarray(object):
def __init__(self):
self.f = open('afile.dat', 'w+')
self.a = array.array('L')
def append(self, n):
self.a.append(n)
if len(self.a) > MAXINMEM:
self.a.tofile(self.f)
del self.a[:]
def pop(self):
if not len(self.a):
try: self.f.seek(-self.a.itemsize * MAXINMEM, os.SEEK_END)
except IOError: return self.a.pop() # ensure normal IndexError &c
try: self.a.fromfile(self.f, MAXINMEM)
except EOFError: pass
self.f.seek(-self.a.itemsize * MAXINMEM, os.SEEK_END)
self.f.truncate()
return self.a.pop()
当然,您可以根据需要添加其他方法(例如,跟踪总长度、添加extend
等),但如果pop
并且append
确实是您所需要的,这应该提供。
可能有几十种方法可以将列表数据存储在文件中而不是内存中。您如何选择将完全取决于您需要对数据执行哪种操作。您需要随机访问第 N 个元素吗?您需要遍历所有元素吗?您会搜索符合特定条件的元素吗?列表元素采用什么形式?你会只在列表的末尾插入,还是在中间?您是否可以将元数据与磁盘上的大量项目一起保存在内存中?等等等等。
一种可能性是将数据结构化,并将其存储在 SQLite 数据库中。
答案非常“取决于”。
你在列表中存储什么?字符串?整数?对象?
与阅读列表相比,该列表的写入频率如何?项目是否只附加在末尾,还是可以在中间修改或插入条目?
如果您只是追加到末尾,那么写入平面文件可能是最简单的方法。
如果您要存储可变大小的对象(例如字符串),则可能会保留每个字符串开头的内存索引,以便您可以快速读取它。
如果您想要字典行为,请查看 db 模块 - dbm、gdbm、bsddb 等。
如果您想要随机访问写入,那么 SQL 数据库可能会更好。
无论您做什么,进入磁盘的速度都会比内存慢几个数量级,但是如果不知道数据将如何使用,就不可能更具体。
编辑: 根据您更新的要求,我将使用一个平面文件并保留最后 N 个元素的内存缓冲区。
你检查过基于pickle的搁置python模块吗?
您可能需要考虑另一种结构:不是列表,而是弄清楚如何使用生成器或自定义迭代器来完成(您的任务)。
你可以试试 blist: https ://pypi.python.org/pypi/blist/
blist 是 Python 列表的直接替代品,在修改大型列表时提供了更好的性能。
现代操作系统将为您处理此问题,而您无需担心。它被称为虚拟内存。
那么面向文档的数据库呢?
有几种选择;我认为目前最知名的是CouchDB,但您也可以使用Tokyo Cabinet或MongoDB。最后一个具有直接从主项目绑定 python 的优点,不需要任何额外的模块。