Python MemoryError:无法分配数组内存
我有一个250 MB的CSV文件,需要读取约7000行和约9000列。每行代表一个图像,每列代表一个像素(灰度值0-255) 我从一个简单的Python MemoryError:无法分配数组内存,python,memory,csv,file-io,numpy,Python,Memory,Csv,File Io,Numpy,我有一个250 MB的CSV文件,需要读取约7000行和约9000列。每行代表一个图像,每列代表一个像素(灰度值0-255) 我从一个简单的np.loadtxt(“data/training_nohead.csv”,delimiter=“,”)开始,但这给了我一个内存错误。我觉得这很奇怪,因为我正在运行64位Python,安装了8 Gig的内存,但它在使用了大约512MB的内存后就死掉了 此后,我尝试了其他几种策略,包括: 导入文件输入并一次读取一行,将它们附加到数组中 读取整个文件后,np.f
np.loadtxt(“data/training_nohead.csv”,delimiter=“,”)
开始,但这给了我一个内存错误。我觉得这很奇怪,因为我正在运行64位Python,安装了8 Gig的内存,但它在使用了大约512MB的内存后就死掉了
此后,我尝试了其他几种策略,包括:
导入文件输入
并一次读取一行,将它们附加到数组中np.fromstring
np.genfromtext
str = " " * 511000000 # Start at 511 MB
while 1:
str = str + " " * 1000 # Add 1 KB at a time
这样做直到1吉格左右才崩溃。为了好玩,我还尝试了:str=“”*2048000000
(填充2个gigs)-这运行起来很顺利。装满了公羊,从来没有抱怨过。所以问题不是我能分配的RAM总量,而是我能分配多少次内存
在找到这篇帖子之前,我一直在谷歌上搜索,但没有结果:
我从答案中复制了代码:
def iter_loadtxt(filename, delimiter=',', skiprows=0, dtype=float):
def iter_func():
with open(filename, 'r') as infile:
for _ in range(skiprows):
next(infile)
for line in infile:
line = line.rstrip().split(delimiter)
for item in line:
yield dtype(item)
iter_loadtxt.rowlength = len(line)
data = np.fromiter(iter_func(), dtype=dtype)
data = data.reshape((-1, iter_loadtxt.rowlength))
return data
调用iter\u loadtxt(“data/training\u nohead.csv”)
这次给出了一个稍微不同的错误:
MemoryError: cannot allocate array memory
用谷歌搜索这个错误,我只发现了一个,没什么帮助,帖子:
在我运行Python2.7时,这不是我的问题。任何帮助都将不胜感激。在@J.F.Sebastian的帮助下,我得出了以下答案:
train = np.empty([7049,9246])
row = 0
for line in open("data/training_nohead.csv")
train[row] = np.fromstring(line, sep=",")
row += 1
当然,这个答案假定事先知道行和列的数量。如果您手头没有此信息,则行数将始终需要一段时间来计算,因为您必须读取整个文件并计数\n
字符。这样就足够了:
num_rows = 0
for line in open("data/training_nohead.csv")
num_rows += 1
对于列数,如果每行的列数相同,则可以只计算第一行,否则需要跟踪最大列数
num_rows = 0
max_cols = 0
for line in open("data/training_nohead.csv")
num_rows += 1
tmp = line.split(",")
if len(tmp) > max_cols:
max_cols = len(tmp)
此解决方案最适用于数字数据,因为包含逗号的字符串可能会使事情变得非常复杂。这是一个古老的讨论,但可能对现在的人们有所帮助 我想我知道为什么
str=str+“”*1000
失败的次数比str=“”*2048000000
在运行第一个对象时,我认为操作系统需要在内存中分配新对象,即str+“”*1000
,然后才引用名称str
。在将名称“str”引用到新对象之前,它无法删除第一个对象。
这意味着操作系统需要在同一时间分配两次“str”对象,使其能够只分配1 gig,而不是2 gig。
我相信使用下一个代码将获得与单次分配相同的操作系统最大内存:
str = " " * 511000000
while(1):
l = len(str)
str = " "
str = " " * (len + 1000)
如果我错了,请随时告诉我你试过两次传球吗?第1步:计算数组维度
nxm
和数据类型。第二步:将数据放入预先分配的数组中(为np指定dtype
,count
。fromiter()
可能就足够了)我实际上已经知道数组的尺寸(7049 x 9146),所以我会试试这个。编辑-9246,而不是9146。不重要,尽管它起作用了!请张贴作为一个答案,所以我可以接受它。加分:它运行了8秒!我非常惊讶,你可以。你已经完成了所有的工作。请添加避免记忆错误的小代码示例。注意:对于i,枚举(文件)中的行
和ncols=max(ncols,len(line.split(','))
您可以在此处使用的内置函数。通常(不是在这种情况下),cvs行可能跨越多个物理行,即枚举csv行的正确方法是:对于i,枚举(csv.reader(file))中的行。
。