内存上限?

Har*_*pal 25 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')
Run Code Online (Sandbox Code Playgroud)

mar*_*eau 30

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

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

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

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

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

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

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()
Run Code Online (Sandbox Code Playgroud)

  • -1(a)OP不是**"试图一次将几个大文件读入内存"; 他一次只读一个.(b)然而,OP在阅读时将每个文件占用的内存加倍[见我的回答].(c)你的代码不起作用; `totals`和`field`是**str**对象; 我们想要**数**总计来计算平均值; 你的总数会变成一些非常长的字符串; 这是Python,不是awk; 你需要在那里抛出几个`float()`(d)`totals = [field in fields in field]`而不是`totals = fields` ??? (6认同)
  • 等等,答案是"没有强加内存限制"? (3认同)

Tim*_*ker 18

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

更好地迭代每一行:

for current_line in u:
    do_something_with(current_line)
Run Code Online (Sandbox Code Playgroud)

是推荐的方法.

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

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

此外,由于您似乎正在处理TSV文件(制表符分隔值),您应该查看将处理所有拆分,删除s等的csv模块\n.


Mic*_*las 17

Python可以使用其环境可用的所有内存.使用about后,我的简单"内存测试"在ActiveState Python 2.6上崩溃了

1959167 [MiB]
Run Code Online (Sandbox Code Playgroud)

在jython 2.5上它崩溃了:

 239000 [MiB]
Run Code Online (Sandbox Code Playgroud)

可能我可以配置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))
Run Code Online (Sandbox Code Playgroud)

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

  • 我错了.它崩溃的原因是默认的32位进程在Windows中获得2GB的限制. (4认同)
  • 我在我的机器上运行你的脚本(win7-64,python27,16GB内存),它在使用1900 [MiB]后崩溃,但是从任务管理器我知道可用的物理内存大约是8000M.所以"Python可以使用其环境可用的所有内存"可能不是真的. (3认同)

Pär*_*der 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
Run Code Online (Sandbox Code Playgroud)


Joh*_*hin 5

您不仅要将每个文件的全部内容读取到内存中,而且还要费力地将信息复制到称为的表中list_of_lines

您有第二个问题:对变量名的选择会严重混淆您的工作。

这是重写的脚本,其中删除了readlines()标题,并使用了有意义的名称:

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')
Run Code Online (Sandbox Code Playgroud)

显而易见,(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
Run Code Online (Sandbox Code Playgroud)