在Python中将大型哈希表存储到文件中

4 投票
7 回答
6040 浏览
提问于 2025-04-15 13:58

你好。我有一个函数想要进行缓存,但它可能的值实在太多了。有没有什么简单的方法可以把这些值存储在一个文本文件里,然后从文件中读取呢?比如说,像把计算好的所有小于10^9的质数存到一个文本文件里?我知道从文本文件读取数据会比较慢,但如果数据量真的很大,那也没有其他办法了。谢谢!

7 个回答

3

你也可以选择一种最简单粗暴的方法,创建一个Python文件,里面只写一条语句:

seedprimes = [3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,
79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173, ...

然后直接导入这个文件就可以了。(这里有一个包含到1万的质数的文件:http://python.pastebin.com/f177ec30。)

from primes_up_to_1e9 import seedprimes
6

你可以使用 shelve模块 来把一个像字典的结构存储到文件里。下面是来自Python文档的说明:

import shelve

d = shelve.open(filename)  # open -- file may get suffix added by low-level
                           # library

d[key] = data              # store data at key (overwrites old data if
                           # using an existing key)
data = d[key]              # retrieve a COPY of data at key (raise KeyError
                           # if no such key)
del d[key]                 # delete data stored at key (raises KeyError
                           # if no such key)

flag = key in d            # true if the key exists
klist = list(d.keys())     # a list of all existing keys (slow!)

# as d was opened WITHOUT writeback=True, beware:
d['xx'] = [0, 1, 2]        # this works as expected, but...
d['xx'].append(3)          # *this doesn't!* -- d['xx'] is STILL [0, 1, 2]!

# having opened d without writeback=True, you need to code carefully:
temp = d['xx']             # extracts the copy
temp.append(5)             # mutates the copy
d['xx'] = temp             # stores the copy right back, to persist it

# or, d=shelve.open(filename,writeback=True) would let you just code
# d['xx'].append(5) and have it work as expected, BUT it would also
# consume more memory and make the d.close() operation slower.

d.close()                  # close it
11

对于一个包含最多到 10**9 的质数的列表,为什么需要用哈希呢?那里的键是什么呢?听起来这正是用一个简单直接的二进制文件的好机会!根据 质数定理,大约有 10**9/ln(10**9) 个这样的质数,也就是大约五千万个,或者稍微少一点。每个质数占用4个字节,那总共也就200MB左右——这正好适合用 array.array("L") 以及它的一些方法,比如 fromfile 等等(具体可以参考 文档)。在很多情况下,你实际上可以把这200MB的数据全部加载到内存中,但在最坏的情况下,你也可以只取其中的一部分(比如通过 mmaparray.arrayfromstring 方法),然后在里面进行二分查找(比如通过 bisect),等等等等。

当你真的需要一个巨大的键值存储时——不是那200MB的小东西,而是几个GB的存储!我以前推荐过 shelve,但在经历了一些不愉快的实际使用后(比如性能、可靠性等问题),我现在更推荐使用数据库引擎——sqlite就很好,而且自带在Python里,PostgreSQL更棒,像CouchDB这样的非关系型数据库可能更好,等等。

撰写回答