处理Python内存使用的可能解决方案

1 投票
5 回答
805 浏览
提问于 2025-04-16 16:04

我有一个这样的类:

 class C1:
    STORE = []
    TYPE = []
    ITEMS = []
    PRICE = []


    def __init__(self,STORE,TYPE,ITEMS,PRICE):
        self.STORE = STORE
        self.TYPE = TYPE
        self.ITEMS = ITEMS
        self.PRICE = PRICE

这个类的目的是存储不同商店里的所有商品及其价格。商品是按字母和数字的顺序排列的,如果某个商店没有某个商品,它的价格就显示为0。我是从一个数据库的表中获取这些数据,表的结构大致是这样的:

           S1  S2  S3 .... S29000
item1      15   2  30 ....    100
item2       0   1   0 ....      5
.
.
.
item600     30 190 10 ....     25

商店和商品的列表分别如下:

商店:['S1','S2',...,'S29000'] 商品:['item1','item2',....,'item600']

价格列表是一个多维列表,通过指定商店的索引和商品的索引,可以得到指定商店中指定商品的价格(例如,price[0][0]会返回S1中item1的价格,15)。

有了这些数据,我在类中运行一些需要“复杂”计算的“报告”。

我遇到的问题是,我从不同的表中创建类对象,结果Python的内存使用量在Windows任务管理器中显示几乎达到了1.8 GB。

我知道我的对象是内存消耗的主要原因,这让我有了两个问题:

  1. 我在使用完每个类对象后都用'del'删除它们,并且调用了垃圾回收(gc),但即使脚本结束后,Python似乎也不想释放内存。有没有什么简单粗暴的方法可以释放内存?

  2. 有没有其他的数据结构可以替代列表,消耗更少的内存并提高我的性能?我注意到Numpy是一个选项,但我被迫使用Python 2.3,似乎与Numpy不兼容。

我之前尝试每次计算时都读取数据库,这样我的程序运行几乎需要3个小时,但现在把数据存储到类中后,时间缩短到了40分钟。所以我的“客户”不想再回到以前的方式。

谢谢你的帮助。

编辑:原始数据看起来就像我之前描述的表格,但只能通过供应商提供的API访问。

编辑2:我的目的是为多个“数据源”创建不同的C1类型对象。所以我最终会有6个C1类型的对象,每个对象包含不同的数据。

编辑3:为了获取每个商店的商品价格列表,API有一个函数,形式是GetPrices('商店名称')。因此,必须为每个商店调用这个函数。目前,我生成C1对象的代码有一个巨大的循环,调用这个函数为每个商店获取价格。

5 个回答

1

你有一个800行、30,000列的矩阵。这意味着总共有24,000,000个元素。如果这些元素是浮点数的话,光是存储这些数据就大约需要100MB的空间,但因为对象的额外开销,实际占用的空间可能更多。而且你还有六个这样的矩阵?

如果1.8GB的内存太多了,那你就得存储更少的数据。抱歉,这就是为什么处理大量数据会很困难。确保你只保留必要的数据,其他的就不要了。

如果这个矩阵大部分都是空的,我建议你看看一些稀疏矩阵的库。SciPy和NumPy是最常用的,但我相信还有其他人提供适合Python 2.3的解决方案。也许可以找找旧版的NumPy?

1

使用Python 2.3会限制你的选择,比如你不能使用64位版本。这也是内存没有被释放回操作系统的主要原因:在CPython中,内部的对象分配器直到2.5版本才有能力把不再使用的内存还给操作系统。

如果可以的话,试着在2.7版本上运行你的算法,看看使用更新的解释器版本能带来什么好处(或者在迁移过程中可能会遇到什么兼容性问题)。

另外,正如其他人所建议的,优化你的数据结构。检查你经常执行的操作的算法复杂度,看看有没有办法把O(n*n)的操作转换为O(n*logn),把O(n)转换为O(logn)或O(1)。

即使底层的数据结构不能改变,你也可以尝试使用bisect模块来加速一些列表操作。

3

你可以试试 array 模块,它在 Python 2.3 就已经有了。除此之外,你可能还想考虑使用一个合适的数据库来处理这些数据。

撰写回答