内存上限?

时间:2010-11-26 12:11:10

标签: python memory

python的内存是否有限制?我一直在使用python脚本来计算文件的平均值,最小值为150mb。

根据文件的大小,我有时会遇到MemoryError

可以为python分配更多内存,所以我没有遇到错误吗?


编辑:现在代码

注意:文件大小可能会有很大差异(最多20GB),文件的最小大小为150mb

file_A1_B1 = open("A1_B1_100000.txt", "r")
file_A2_B2 = open("A2_B2_100000.txt", "r")
file_A1_B2 = open("A1_B2_100000.txt", "r")
file_A2_B1 = open("A2_B1_100000.txt", "r")
file_write = open ("average_generations.txt", "w")
mutation_average = open("mutation_average", "w")

files = [file_A2_B2,file_A2_B2,file_A1_B2,file_A2_B1]

for u in files:
    line = u.readlines()
    list_of_lines = []
    for i in line:
        values = i.split('\t')
        list_of_lines.append(values)

    count = 0
    for j in list_of_lines:
        count +=1

    for k in range(0,count):
        list_of_lines[k].remove('\n')

    length = len(list_of_lines[0])
    print_counter = 4

    for o in range(0,length):
        total = 0
        for p in range(0,count):
            number = float(list_of_lines[p][o])
            total = total + number
        average = total/count
        print average
        if print_counter == 4:
            file_write.write(str(average)+'\n')
            print_counter = 0
        print_counter +=1
file_write.write('\n')

5 个答案:

答案 0 :(得分:30)

(这是我的第三个答案,因为我误解了你的代码在原版中所做的事情,然后在我的第二个希望三个人的魅力中犯了一个小而重要的错误。

编辑:由于这似乎是一个受欢迎的答案,我已做了一些修改以改进其实施多年来 - 最不太重要。如果人们将其用作模板,那么这将是一个更好的基础。

正如其他人所指出的那样,你的MemoryError问题很可能是因为你试图将大文件的全部内容读入内存,然后,最重要的是,有效地将所需内存量增加一倍。创建每行的字符串值列表列表。

Python的内存限制取决于您的计算机和操作系统可用的物理内存和虚拟内存磁盘空间。即使你没有全部使用它并且你的程序“有效”,使用它可能是不切实际的,因为它需要太长时间。

无论如何,最明显的避免方法是一次处理一行一行,这意味着你必须逐步处理。

为此,保留每个字段的运行总计列表。完成后,可以通过将相应的总值除以读取的总行数来计算每个字段的平均值。完成后,可以打印出这些平均值,并将一些平均值写入其中一个输出文件。我也有意识地使用非常具有描述性的变量名来试图让它变得易于理解。

try:
    from itertools import izip_longest
except ImportError:    # Python 3
    from itertools import zip_longest as izip_longest

GROUP_SIZE = 4
input_file_names = ["A1_B1_100000.txt", "A2_B2_100000.txt", "A1_B2_100000.txt",
                    "A2_B1_100000.txt"]
file_write = open("average_generations.txt", 'w')
mutation_average = open("mutation_average", 'w')  # left in, but nothing written

for file_name in input_file_names:
    with open(file_name, 'r') as input_file:
        print('processing file: {}'.format(file_name))

        totals = []
        for count, fields in enumerate((line.split('\t') for line in input_file), 1):
            totals = [sum(values) for values in
                        izip_longest(totals, map(float, fields), fillvalue=0)]
        averages = [total/count for total in totals]

        for print_counter, average in enumerate(averages):
            print('  {:9.4f}'.format(average))
            if print_counter % GROUP_SIZE == 0:
                file_write.write(str(average)+'\n')

file_write.write('\n')
file_write.close()
mutation_average.close()

答案 1 :(得分:18)

您正在将整个文件读入内存(line = u.readlines()),如果文件太大(并且您说有些文件高达20 GB),这将失败,所以这就是您的问题。

更好地迭代每一行:

for current_line in u:
    do_something_with(current_line)

是推荐的方法。

稍后在您的脚本中,您正在做一些非常奇怪的事情,比如先计算列表中的所有项目,然后在该计数范围内构建for循环。为什么不直接迭代列表呢?你的脚本的目的是什么?我的印象是,这可以更轻松地完成。

这是Python等高级语言的优势之一(与C相反,您必须自己完成这些内务处理任务):允许Python为您处理迭代,并且只在内存中收集您实际需要的内容在任何特定的时间记忆。

此外,由于您似乎正在处理TSV文件(制表符分隔值),您应该查看csv module,它将处理所有拆分,删除\n等为了你。

答案 2 :(得分:15)

Python可以使用其环境可用的所有内存。在使用about

之后,我的简单“内存测试”在ActiveState Python 2.6上崩溃了
1959167 [MiB]

在jython 2.5上,它早先崩溃了:

 239000 [MiB]

可能我可以配置Jython来使用更多内存(它使用来自JVM的限制)

测试应用:

import sys

sl = []
i = 0
# some magic 1024 - overhead of string object
fill_size = 1024
if sys.version.startswith('2.7'):
    fill_size = 1003
if sys.version.startswith('3'):
    fill_size = 497
print(fill_size)
MiB = 0
while True:
    s = str(i).zfill(fill_size)
    sl.append(s)
    if i == 0:
        try:
            sys.stderr.write('size of one string %d\n' % (sys.getsizeof(s)))
        except AttributeError:
            pass
    i += 1
    if i % 1024 == 0:
        MiB += 1
        if MiB % 25 == 0:
            sys.stderr.write('%d [MiB]\n' % (MiB))

在您的应用中,您可以立即阅读整个文件。对于这样的大文件,你应该逐行阅读。

答案 3 :(得分:8)

不,Python应用程序的内存使用没有特定于Python的限制。我经常使用可能使用几千兆字节内存的Python应用程序。最有可能的是,您的脚本实际上使用的内存超过了您运行的计算机上的可用内存。

在这种情况下,解决方案是重写脚本以提高内存效率,或者如果脚本已经过优化以最大限度地减少内存使用,则添加更多物理内存。

修改

您的脚本会立即将文件的全部内容读入内存(line = u.readlines())。由于您处理的文件大小不超过20 GB,因此除非您的计算机中有大量内存,否则您将会遇到内存错误。

更好的方法是一次读取一行文件:

for u in files:
     for line in u: # This will iterate over each line in the file
         # Read values from the line, do necessary calculations

答案 4 :(得分:5)

您不仅要将每个文件的整个内容读入内存,还要在名为list_of_lines的表格中费力地复制信息。

您有一个次要问题:您对变量名称的选择严重模糊了您正在做的事情。

这是你的脚本被删除的readlines()caper重写并带有有意义的名字:

file_A1_B1 = open("A1_B1_100000.txt", "r")
file_A2_B2 = open("A2_B2_100000.txt", "r")
file_A1_B2 = open("A1_B2_100000.txt", "r")
file_A2_B1 = open("A2_B1_100000.txt", "r")
file_write = open ("average_generations.txt", "w")
mutation_average = open("mutation_average", "w") # not used
files = [file_A2_B2,file_A2_B2,file_A1_B2,file_A2_B1]
for afile in files:
    table = []
    for aline in afile:
        values = aline.split('\t')
        values.remove('\n') # why?
        table.append(values)
    row_count = len(table)
    row0length = len(table[0])
    print_counter = 4
    for column_index in range(row0length):
        column_total = 0
        for row_index in range(row_count):
            number = float(table[row_index][column_index])
            column_total = column_total + number
        column_average = column_total/row_count
        print column_average
        if print_counter == 4:
            file_write.write(str(column_average)+'\n')
            print_counter = 0
        print_counter +=1
file_write.write('\n')

很明显,(1)你正在计算列平均值(2)混淆导致其他人认为你在计算行平均值。

在计算列平均值时,在每个文件结束之前不需要输出,实际需要的额外内存量与列数成正比。

以下是外循环代码的修订版本:

for afile in files:
    for row_count, aline in enumerate(afile, start=1):
        values = aline.split('\t')
        values.remove('\n') # why?
        fvalues = map(float, values)
        if row_count == 1:
            row0length = len(fvalues)
            column_index_range = range(row0length)
            column_totals = fvalues
        else:
            assert len(fvalues) == row0length
            for column_index in column_index_range:
                column_totals[column_index] += fvalues[column_index]
    print_counter = 4
    for column_index in column_index_range:
        column_average = column_totals[column_index] / row_count
        print column_average
        if print_counter == 4:
            file_write.write(str(column_average)+'\n')
            print_counter = 0
        print_counter +=1