python 加载比文件实际大小更多的内存
python loads more memory than the actual size of the file
我有一个大约 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 循环中没有'break' 命令,这意味着我实际上读取了文件的全部内容。当脚本运行 运行 时,我从 'htop' 命令中注意到它占用了 156G 的虚拟内存(VIRT 列)和几乎相同数量的常驻内存(RES 列)。为什么我的脚本使用 156G 而文件大小只有 28G?
您需要使用生成器懒惰地逐行读取它。试试这个:
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 循环中添加您的逻辑,这样您就不必等待整个过程完成。
Python 对象有很多无意中听到的内容,例如对象的引用计数和其他内容。这意味着 Python 浮点数超过 8 个字节。在我的 32 位 Python 版本上,它是
>>> import sys
>>> print(sys.getsizeof(float(0))
16
列表有其自身的开销,因此每个元素需要 4 个字节来存储对该对象的引用。所以100个float在一个list中实际占用的大小为
>>> 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,但我不太了解它是否更适合你。
你能w/o存储每个元组吗? IE。 "do something" 可以在您读入文件时发生吗?如果是这样...试试这个:
#!/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
我有一个大约 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 循环中没有'break' 命令,这意味着我实际上读取了文件的全部内容。当脚本运行 运行 时,我从 'htop' 命令中注意到它占用了 156G 的虚拟内存(VIRT 列)和几乎相同数量的常驻内存(RES 列)。为什么我的脚本使用 156G 而文件大小只有 28G?
您需要使用生成器懒惰地逐行读取它。试试这个:
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 循环中添加您的逻辑,这样您就不必等待整个过程完成。
Python 对象有很多无意中听到的内容,例如对象的引用计数和其他内容。这意味着 Python 浮点数超过 8 个字节。在我的 32 位 Python 版本上,它是
>>> import sys
>>> print(sys.getsizeof(float(0))
16
列表有其自身的开销,因此每个元素需要 4 个字节来存储对该对象的引用。所以100个float在一个list中实际占用的大小为
>>> 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,但我不太了解它是否更适合你。
你能w/o存储每个元组吗? IE。 "do something" 可以在您读入文件时发生吗?如果是这样...试试这个:
#!/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