【问题标题】:Iterate over list using mmap - Python使用 mmap 遍历列表 - Python
【发布时间】:2014-11-12 18:47:20
【问题描述】:

是否可以使用 mmap 文件遍历列表? 关键是列表太大(超过 3 000 000 项)。我需要在启动程序时快速访问此列表,因此启动程序后我无法将其加载到内存中,因为它需要几秒钟。

with open('list','rb') as f:
    mmapList = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) # As far as I'm concerned, now I have the list mapped in a virtual memory.

现在,我想遍历这个列表。

for a in mmapList 不起作用。

编辑:我知道的唯一方法是将列表项保存为 txt 文件中的行,然后使用 readline 但我很好奇是否有更好更快的方法。

【问题讨论】:

  • 列表是如何保存到该文件中的?
  • @pbkhrv 它是使用 cPickle 保存的,但我可以更改它。
  • mmap 对象充当一个字符串 (docs.python.org/2/library/mmap.html),因此如果不先将整个内容加载到内存中,使用 cPickle 反序列化您的列表并不是一个真正的选择。但是,可以编写一个简单的生成器,这样“for a in mmapList”仍然可以通过使用 readline() 逐步遍历 mmap 来工作。这能解决你的问题吗?
  • 实际上,有一种方法可以做到这一点,并且仍然使用泡菜。看我的回答。

标签: python mapping mmap


【解决方案1】:

您不需要使用 mmap 来遍历 cPickled 列表。您需要做的不是腌制整个列表,而是腌制并转储每个元素,然后从文件中一个一个地读取它们(可以使用生成器)。

代码:

import pickle

def unpickle_iter(f):
  while True:
    try:
      obj = pickle.load(f)
    except EOFError:
      break
    yield obj

def save_list(list, path):
  with open(path, 'w') as f:
    for i in list:
        pickle.dump(i, f)

def load_list(path):
  with open(path, 'r') as f:
     # here is your nice "for a in mmaplist" equivalent:
     for obj in unpickle_iter(f):
        print 'Loaded object:', obj

save_list([1,2,'hello world!', dict()], 'test-pickle.dat')
load_list('test-pickle.dat')

输出:

Loaded object: 1
Loaded object: 2
Loaded object: hello world!
Loaded object: {}

【讨论】:

  • 感谢您的建议。我试过这段代码,它可以工作。但我不得不回到文本保存解决方案,因为这需要太多时间。在我的例子中,保存文本的 mmap 解决方案需要 1.9 秒,而这个解决方案需要 7.8 秒。
  • 有趣,听起来像 unpickling 会增加一些开销。如果性能是一个问题,这里有一个关于各种序列化方法的有趣讨论:stackoverflow.com/questions/9662757/…
猜你喜欢
  • 2013-02-18
  • 1970-01-01
  • 2018-03-08
  • 2015-10-07
  • 2013-07-13
  • 1970-01-01
相关资源
最近更新 更多