You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Python 2.7执行b.append(int(j))时触发Memory Error的问题咨询

解决Python 2.7中读取小文件却触发Memory Error的问题

首先,咱们得先理清楚为什么2.8MB的文件会让28GB内存的机器爆内存——这看起来很反直觉,但问题大概率出在你处理数据的方式,而不是文件本身的大小。

可能的原因分析

  1. 单个超大整数的转换开销
    如果你的0.txt里是一整行数百万位的纯数字字符串(比如一个2.8MB长的数字),那把它转换成Python的int时,因为Python的整数是任意精度的,内部会用数组来存储二进制形式的数字,再加上Python对象的额外开销(引用计数、类型信息等),这个转换过程可能会瞬间占用远超文本大小的内存——虽然28GB看起来很大,但极端情况下(比如数字长度达到数千万位),还是可能触发内存错误。

  2. 逐个字符转int并存储到列表
    如果你的代码是遍历每行的每个字符,把每个字符转成int后添加到列表里(比如for j in line: b.append(int(j))),那2.8MB的文本大概有290万个字符。在64位Python2.7中,每个int对象大约要占28字节,290万*28字节≈81MB——理论上这远小于你的内存,但如果你的代码同时还有其他内存占用,或者存在内存碎片问题,也可能触发错误。

  3. 分割成大量小整数的内存累积
    如果文本是用分隔符(比如逗号、空格)分割的大量数字,每个数字转成int后都存在列表里,虽然单个int不大,但架不住数量多——不过几百万个int也才几百MB,还是不至于让28GB内存爆掉,除非你还有其他内存密集型操作。

解决方案

根据不同的场景,你可以试试下面的方法:

  • 避免不必要的大整数转换
    如果你的业务不需要把那个超长数字转成int(比如只是需要校验、截取部分数字),直接操作字符串就行,完全不用转换,这样内存占用就是文件本身的大小。

  • 用生成器分批处理,不要全存到列表
    如果需要处理分割后的多个数字,别一次性把所有数字都存入列表,而是用生成器按需生成,处理完一个就释放一个:

    def get_numbers(file_path):
        with open(file_path, 'r') as f:
            line = f.read().strip()
            # 这里假设用逗号分隔,根据你的实际分隔符修改
            for num_str in line.split(','):
                yield int(num_str)
    
    # 逐个处理数字,不用一次性存到列表
    for num in get_numbers('0.txt'):
        # 这里写你的处理逻辑
        print(num)
    
  • 使用更高效的数据结构
    如果必须存储大量整数,用Python的array模块代替普通列表——它存储的是原始二进制数据,内存占用比普通列表小得多:

    import array
    
    # 用'l'表示长整型,根据你的数字大小选合适的类型(比如'i'是普通int)
    num_array = array.array('l')
    with open('0.txt', 'r') as f:
        line = f.read().strip()
        for num_str in line.split(','):
            num_array.append(int(num_str))
    

    这种方式每个整数只占用4或8字节,比普通列表的28字节节省了70%以上的内存。

  • 考虑升级到Python3
    Python2.7已经停止维护多年,Python3在内存管理、大整数处理上都有不少优化,很多Python2的内存问题在Python3里都能自动解决。

内容的提问来源于stack exchange,提问作者papabiceps

火山引擎 最新活动