从文件中读取数字列表的最快方法
我在Stack Overflow中发现了一些类似的问题,但我相信我可以从特定于我的案例的建议中受益。从文件中读取数字列表的最快方法
我必须在一个文件中存储大约8万个实值数字列表,并在稍后读取它们。
首先,我想cPickle
,但阅读时间没有吸引力:
>>> stmt = """
with open('pickled-data.dat') as f:
data = cPickle.load(f)
"""
>>> timeit.timeit(stmt, 'import cPickle', number=1)
3.8195440769195557
后来我发现,存储数字作为明文允许更快的读取(有道理的,因为cPickle
必须担心很多东西):
>>> stmt = """
data = []
with open('text-data.dat') as f:
for line in f:
data.append([float(x) for x in line.split()])
"""
>>> timeit.timeit(stmt, number=1)
1.712096929550171
这是一个很好的改善,但我认为我仍然可以优化它在某种程度上,因为其他语言编写的程序可以从文件中显着更快的读取类似的数据。
任何想法?
如果numpy的阵列是可行的,numpy.fromfile
将可能是读取文件(这里有一个somewhat related question我问只是一对夫妇日前)
或者,好像你的表现会更好一点与struct
最快的选项,尽管我还没有测试过它:
import struct
def write_data(f,data):
f.write(struct.pack('i',len()))
for lst in data:
f.write(struct.pack('i%df'%len(lst),len(lst),*lst))
def read_data(f):
def read_record(f):
nelem = struct.unpack('i',f.read(4))[0]
return list(struct.unpack('%df'%nelem,f.read(nelem*4))) #if tuples are Ok, remove the `list`.
nrec = struct.unpack('i',f.read(4))[0]
return [ read_record(f) for i in range(nrec) ]
这假定将数据存储为4字节的浮点数就足够了。如果您想要一个真正的双精度数字,请将格式语句从f更改为d并将nelem*4
更改为nelem*8
。这里可能存在一些次要的可移植性问题(例如,数据类型的字节顺序和sizeof)。
我怀疑numpy fromfile是相对优化的,可能是比结构,情况允许更好的解决方案。 – jmetz 2012-08-02 14:38:01
@mutzmatron - 是的,可能 - 虽然真的不应该有太大的差异。我敢打赌,他们几乎完成同样的事情 - numpy的优点是它可以将对象放入顺序存储器中(本质上只需要分配1块和1个指针来操作指针)。另一方面struct可能仍然只分配一个块,但它也需要一个读取每个浮点的指针,所以这是一个额外的工作。无论哪种方式,我希望它比读取ASCII文本更快,将其转换为浮动(全部在非类型化的python框架内完成)。 – mgilson 2012-08-02 14:41:14
谢谢,'numpy.fromfile'耗时0.02秒。 – erickrf 2012-08-02 16:04:06
如果你存储这么多的列表,sqlite数据库是不是一个更好的数据结构? – BrtH 2012-08-02 14:28:13
您是否尝试过'csv'模块的阅读器?它会避免你所调用的手动分割。 – jmetz 2012-08-02 14:28:56
@BrtH数据库看起来像是一种矫枉过正,我只需要加载所有这些列表。 – erickrf 2012-08-02 15:46:39