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

Vin*_*ent 12 python memory-management file list 32bit-64bit

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

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

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

Ale*_*lli 14

如果您的"数字"足够简单(每个最多4个字节的有符号或无符号整数,或每个4或8个字节的浮点数),我建议使用标准库阵列模块作为保留数百万个数据库的最佳方法在内存中("虚拟阵列"的"提示"),用二进制文件(打开二进制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()
Run Code Online (Sandbox Code Playgroud)

当然,你可以添加其他的方法在必要时(如跟踪的总长度,加extend,等等),但如果popappend确实是你所需要的这应有助于.


Ned*_*der 8

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

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


Dav*_*rby 6

答案非常"取决于".

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

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

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

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

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

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

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

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