我有一个大约28Gb的3列文件。我想用python阅读它并将其内容放在3D元组列表中。以下是我使用的代码:
f = open(filename)
col1 = [float(l.split()[0]) for l in f]
f.seek(0)
col2 = [float(l.split()[1]) for l in f]
f.seek(0)
col3 = [float(l.split()[2]) for l in f]
f.close()
rowFormat = [col1,col2,col3]
tupleFormat = zip(*rowFormat)
for ele in tupleFormat:
### do something with ele
没有'休息' for循环中的命令,意味着我实际上读取了文件的整个内容。当脚本运行时,我注意到了“htop”的问题。命令它需要156G的虚拟内存(VIRT列)和几乎相同的驻留内存(RES列)。为什么我的脚本使用156G而文件大小只有28G?
答案 0 :(得分:2)
Python对象有很多被无意中听到,例如,对象的引用计数和其他东西。这意味着Python float超过8个字节。在我的32位Python版本上,它是
>>> import sys
>>> print(sys.getsizeof(float(0))
16
列表有自己的开销,然后每个元素需要4个字节来存储对该对象的引用。因此,列表中的100个浮点数实际上占用了
的大小>>> a = map(float, range(100))
>>> sys.getsizeof(a) + sys.getsizeof(a[0])*len(a)
2036
现在,一个numpy数组是不同的。它有一点开销,但引擎盖下的原始数据存储在C中。
>>> import numpy as np
>>> b = np.array(a)
>>> sys.getsizeof(b)
848
>>> b.itemsize # number of bytes per element
8
因此Python浮点数需要20个字节,而numpy需要8个字节。并64bit Python versions require even more。
实际上,如果你必须在内存中加载大量数据,那么numpy就是一种方式。看一下加载数据的方式,我假设它是文本格式,每行有3个浮点数,由任意数量的空格分隔。在这种情况下,您可以使用numpy.genfromtxt()
data = np.genfromtxt(fname, autostrip=True)
您还可以查找更多选项here,例如mmap,但我不太了解它是否适合您。
答案 1 :(得分:0)
你需要使用生成器懒洋洋地逐行阅读。试试这个:
col1 = []
col2 = []
col3 = []
rowFormat = [col1, col2, col3]
with open('test', 'r') as f:
for line in f:
parts = line.split()
col1.append(float(parts[0]))
col2.append(float(parts[1]))
col3.append(float(parts[2]))
# if possible do something here to start seeing results immediately
tupleFormat = zip(*rowFormat)
for ele in tupleFormat:
### do something with ele
您可以在for循环中添加逻辑,这样就不必等待整个过程完成。
答案 2 :(得分:0)
你可以通过存储每个元组来获得吗?即你在文件中阅读时会“做某事”吗?如果是这样的话......试试这个:
#!/usr/bin/env python
import fileinput
for line in fileinput.FileInput('test.dat'):
ele = tuple((float(x) for x in line.strip().split()))
# Replace 'print' with your "do something".
# Note that ele is now a generator, not a tuple. Wrap it in
# ele = tuple(ele) to get a tuple instead if you need it.
print ele
如果没有,也许您可以通过选择列格式或元组格式列表来节省一些内存,但不能同时保存一些内存....
#!/usr/bin/env python
import fileinput
elements = []
for line in fileinput.FileInput('test.dat'):
elements.append(tuple((float(x) for x in line.strip().split())))
for ele in elements:
# do something