我正在阅读大小为24 GB
的文件。我正在使用
lines = open(fname).read().splitlines()
似乎在读取行时,它总是使用〜应该需要的RAM量的两倍。它使用大约50 GB
作为我当前的脚本(在它跳到50之后再回到28)但是每次我使用这种行来读取Python
中的文件时它通常使用双倍文件大小在下降到我期望的大小之前。
知道为什么会这样或者我怎么能避免它?
答案 0 :(得分:2)
RAM使用:Filesize * 1:将整个文件读入内存
open(fname).read()
RAM使用文件大小* 2:在列表中分配足够的空间以拆分换行符
open(fname).read().splitlines()
此操作完成后,RAM使用量将下降至约Filesize * 1,因为不再需要该文件的全文,并且可以对其进行垃圾回收。
如果您不需要同时使用该文件的全文,并且只在线上操作,那么只需遍历该文件
with open(filename) as f:
for line in f:
# do something
答案 1 :(得分:0)
如果文件包含25Gb的数据,则file_handle.read()
将返回大小为25Gb的字符串。拆分该字符串时,您将创建一个列表,该列表包含最多可添加25Gb数据的字符串(以及每个字符串的额外字符串开销)。所以你最终使用了大约两倍的内存。
垃圾收集器几乎可以立即获得大字符串,使得新的python对象可以占用内存,但这并不意味着内存完全被释放到操作系统(由于python中的优化和#39;内存分配器)。
更好的方法是一次累积一个行列表:
with open(filename) as f:
lines = list(f)
你只能在 1 的时间内从文件中保存大约一行内存,这样你的内存使用将主要只是存储列表的内存。
1 这并不完全正确... pythons内部线路缓冲在任何给定时间缓冲都可能有几kb的数据... < / p>
当然,可能还有迭代处理文件的选项:
with open(filename) as f:
for line in f:
process(line)
答案 2 :(得分:0)
我的猜测是read
返回整个文件的字符串,在从splitlines
返回列表之前不会对其进行垃圾回收。如果需要内存中的文件,请尝试readlines
方法:
with open(fname) as f:
lines = f.readlines()
答案 3 :(得分:0)
read()
尝试将整个文件加载到内存中。使用开销和缓冲区,这可能会超出文件的大小。然后你将文件的内容拆分成行,因为python为每一行分配了新的内存。
您的代码是否可以重构为使用readline()
并逐个处理这些行?这会减少程序一次使用的内存量。
with open(filename) as f:
for line in f:
# process a single line, maybe keeping some state elsewhere.
但是,如果您仍然需要一次加载内存中的所有行,请改用readlines()
:
with open(filename) as f:
lines = f.readlines()
答案 4 :(得分:0)
read()
返回单个str
,其中包含整个文件数据。 splitlines
正在使用相同的数据返回list
lines
。在splitlines
创建list
之后,整个文件数据都不会被清除,因此您可以在短时间内存储两份数据。
如果您想最大限度地减少这种开销(并且仍然会删除换行符),您可以尝试:
with open(fname) as f:
lines = [line.rstrip('\r\n') for line in f]
如果您可以逐行处理(一次不需要整个list
),那就更好了:
with open(fname) as f:
for line in f:
line = line.rstrip('\r\n')
避免一次存储两行以上。
答案 5 :(得分:0)
您使用以下内容将整个文件读入内存:
open(fname).read()
在第二步中,您使用.splitlines()
从此字符串创建列表。
在此期间,字符串保留在内存中,但您复制了部分内容
字符串逐行进入列表。只有在你完成创建后
列表,字符串可以被垃圾收集。所以在这段时间你会存储
所有信息两次,因此需要两倍的内存。
您可以使用open(fname).readlines()
或逐行阅读文件以减少
内存占用。