据我所知,您读取文件的方法已经非常节省内存。
我假设使用
open
获取文件对象
不会将整个文件从文件系统读入RAM,而是根据需要访问文件系统中的文件。
然后,您遍历文件对象,
逐行生成(在您的情况下是字符串,因为您以文本模式打开了文件),即文件对象充当一个
生成器。因此,可以假定这里没有构建所有行的列表,并且逐行读取以连续消耗。
您在列表推导中执行此操作。列表推导是否会在将其右侧(
in
关键字后面的部分)生成的所有值传递给左侧(
for
关键字前面的部分)进行处理之前收集它们?通过一些实验,我们可以得出结论:
print('defining generator function')
def firstn(n):
num = 0
while num < n:
print('yielding ' + str(num))
yield num
num += 1
print('--')
[print('consuming ' + str(i)) for i in firstn(5)]
上述的输出是:
defining generator function
--
yielding 0
consuming 0
yielding 1
consuming 1
yielding 2
consuming 2
yielding 3
consuming 3
yielding 4
consuming 4
因此,答案是否定的,每个生成的值在从右侧生成任何其他值之前立即由左侧消耗。文件中只需要保留一行内存。
因此,如果您的文件中的单独行不太长,则您的读取方法似乎是最节省内存的方法。
当然,您的列表压缩仍然必须收集左侧处理的结果。毕竟,生成的列表就是您想要从所有这些内容中获得的东西。因此,如果您用尽了内存,很可能是由于生成的列表变得过大。
我不知道NumPy是否利用了布尔集合可以比数字更有效地存储的事实。但是,如果它确实这样做,您必须让它意识到您的整数实际上是布尔值,以从更节省内存的数据类型中受益:
import numpy as np
f = open ( "data.txt" , 'r')
converted_data = [ np.fromstring(line, dtype=bool, sep=',') for line in f ]
如果你不需要一次性使用所有的
converted_data
,而是需要能够迭代它,考虑将它也变成一个生成器,而不是一个列表。你不需要费心使用
yield
关键字来实现这个目标。只需将列表推导式中的方括号替换为圆括号,就可以得到一个生成器表达式:
converted_data_generator = ( np.fromstring(line, dtype=bool, sep=',') for line in f )
converted_data
的占用空间感兴趣(除非你能利用稀疏结构,否则它将大于1G)? - das-g