如果我在python中有一个可能超出可用内存地址空间的列表(或数组,字典......),(32位python)有哪些选项和相对速度? (除了没有列出那么大的名单) 列表可以超过内存,但我无法事先知道。一旦它开始超过75%我想不再将列表保留在内存中(或者无论如何都是新项目),有没有办法在流中转换为基于文件的方法?
什么是最好的(速度进出)文件存储选项?
只需要存储一个简单的数字列表。无需随机第N个元素访问,只需追加/弹出类型操作。
答案 0 :(得分:14)
如果您的“数字”足够简单(每个最多4个字节的有符号或无符号整数,或者每个浮点数为4或8个字节),我建议使用标准库array模块作为最佳方法使用二进制文件(打开二进制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
确实是您需要的全部内容应该服务。
答案 1 :(得分:8)
可能有很多方法可以将列表数据存储在文件中而不是内存中。您如何选择这样做将完全取决于您需要对数据执行何种操作。你需要随机访问第N个元素吗?你需要迭代所有元素吗?您会搜索符合特定条件的元素吗?列表元素采用什么形式?你只会插入列表的末尾,还是插入中间?是否有元数据可以保存在内存中,磁盘上有大量项目?等等等等。
一种可能性是以关系方式构建数据,并将其存储在SQLite数据库中。
答案 2 :(得分:6)
答案非常“取决于”。
你在列表中存储了什么?字符串?整数?对象
与阅读相比,列表的编写频率是多少?项目是否仅附加在最后,还是可以在中间修改或插入条目?
如果你只是追加到最后,那么写一个平面文件可能是最简单的事情。
如果要存储可变大小的对象(如字符串),则可以保留每个字符串开头的内存索引,以便快速阅读。
如果你想要字典行为,那么看看db模块 - dbm,gdbm,bsddb等。
如果你想随机访问写作,那么SQL数据库可能会更好。
无论你做什么,进入磁盘的速度都会比内存慢几个数量级,但如果不知道如何使用数据,就不可能更具体。
修改强> 根据您更新的要求,我将使用平面文件并保留最后N个元素的内存缓冲区。
答案 3 :(得分:4)
答案 4 :(得分:2)
您是否检查了搁置基于pickle的python模块?
答案 5 :(得分:1)
您可能想要考虑一种不同类型的结构:不是列表,而是通过生成器或自定义迭代器确定如何执行(您的任务)。
答案 6 :(得分:0)
现代操作系统将为您处理此问题,而无需担心。它被称为virtual memory。
答案 7 :(得分:0)
面向文档的数据库怎么样? 有几种选择;我认为目前最知名的一个是CouchDB,但您也可以选择Tokyo Cabinet或MongoDB。最后一个具有直接来自主项目的python绑定的优点,而不需要任何额外的模块。
答案 8 :(得分:0)
你可以试试blist: https://pypi.python.org/pypi/blist/
blist是Python列表的替代品,可以在修改大型列表时提供更好的性能。