将大型列表保存在内存中的替代方法(python)

时间:2010-01-01 18:31:57

标签: python file list memory-management 32bit-64bit

如果我在python中有一个可能超出可用内存地址空间的列表(或数组,字典......),(32位python)有哪些选项和相对速度? (除了没有列出那么大的名单) 列表可以超过内存,但我无法事先知道。一旦它开始超过75%我想不再将列表保留在内存中(或者无论如何都是新项目),有没有办法在流中转换为基于文件的方法?

什么是最好的(速度进出)文件存储选项?

只需要存储一个简单的数字列表。无需随机第N个元素访问,只需追加/弹出类型操作。

9 个答案:

答案 0 :(得分:14)

如果您的“数字”足够简单(每个最多4个字节的有符号或无符号整数,或者每个浮点数为4或8个字节),我建议使用标准库array模块作为最佳方法使用二进制文件(打开二进制R / W)将数百万个内存保存在内存中(“虚拟阵列”的“提示”),支持磁盘上的其余结构。 array.array具有非常快的fromfiletofile方法,可以方便地来回移动数据。

即,基本上,假设例如无符号长数字,例如:

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,等等),但如果popappend确实是您需要的全部内容应该服务。

答案 1 :(得分:8)

可能有很多方法可以将列表数据存储在文件中而不是内存中。您如何选择这样做将完全取决于您需要对数据执行何种操作。你需要随机访问第N个元素吗?你需要迭代所有元素吗?您会搜索符合特定条件的元素吗?列表元素采用什么形式?你只会插入列表的末尾,还是插入中间?是否有元数据可以保存在内存中,磁盘上有大量项目?等等等等。

一种可能性是以关系方式构建数据,并将其存储在SQLite数据库中。

答案 2 :(得分:6)

答案非常“取决于”。

你在列表中存储了什么?字符串?整数?对象

与阅读相比,列表的编写频率是多少?项目是否仅附加在最后,还是可以在中间修改或插入条目?

如果你只是追加到最后,那么写一个平面文件可能是最简单的事情。

如果要存储可变大小的对象(如字符串),则可以保留每个字符串开头的内存索引,以便快速阅读。

如果你想要字典行为,那么看看db模块 - dbm,gdbm,bsddb等。

如果你想随机访问写作,那么SQL数据库可能会更好。

无论你做什么,进入磁盘的速度都会比内存慢几个数量级,但如果不知道如何使用数据,就不可能更具体。

修改 根据您更新的要求,我将使用平面文件并保留最后N个元素的内存缓冲区。

答案 3 :(得分:4)

好吧,如果你正在寻找速度而你的数据本质上是数字的,你可以考虑使用numpy和PyTablesh5py。根据我的记忆,界面不如简单列表那么好,但可扩展性非常棒!

答案 4 :(得分:2)

您是否检查了搁置基于pickle的python模块?

http://docs.python.org/library/shelve.html

答案 5 :(得分:1)

您可能想要考虑一种不同类型的结构:不是列表,而是通过生成器或自定义迭代器确定如何执行(您的任务)。

答案 6 :(得分:0)

现代操作系统将为您处理此问题,而无需担心。它被称为virtual memory

答案 7 :(得分:0)

面向文档的数据库怎么样? 有几种选择;我认为目前最知名的一个是CouchDB,但您也可以选择Tokyo CabinetMongoDB。最后一个具有直接来自主项目的python绑定的优点,而不需要任何额外的模块。

答案 8 :(得分:0)

你可以试试blist: https://pypi.python.org/pypi/blist/

  

blist是Python列表的替代品,可以在修改大型列表时提供更好的性能。