处理Python内存使用的可能解决方案
我有一个这样的类:
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。
我知道我的对象是内存消耗的主要原因,这让我有了两个问题:
我在使用完每个类对象后都用'del'删除它们,并且调用了垃圾回收(gc),但即使脚本结束后,Python似乎也不想释放内存。有没有什么简单粗暴的方法可以释放内存?
有没有其他的数据结构可以替代列表,消耗更少的内存并提高我的性能?我注意到Numpy是一个选项,但我被迫使用Python 2.3,似乎与Numpy不兼容。
我之前尝试每次计算时都读取数据库,这样我的程序运行几乎需要3个小时,但现在把数据存储到类中后,时间缩短到了40分钟。所以我的“客户”不想再回到以前的方式。
谢谢你的帮助。
编辑:原始数据看起来就像我之前描述的表格,但只能通过供应商提供的API访问。
编辑2:我的目的是为多个“数据源”创建不同的C1类型对象。所以我最终会有6个C1类型的对象,每个对象包含不同的数据。
编辑3:为了获取每个商店的商品价格列表,API有一个函数,形式是GetPrices('商店名称')。因此,必须为每个商店调用这个函数。目前,我生成C1对象的代码有一个巨大的循环,调用这个函数为每个商店获取价格。
5 个回答
你有一个800行、30,000列的矩阵。这意味着总共有24,000,000个元素。如果这些元素是浮点数的话,光是存储这些数据就大约需要100MB的空间,但因为对象的额外开销,实际占用的空间可能更多。而且你还有六个这样的矩阵?
如果1.8GB的内存太多了,那你就得存储更少的数据。抱歉,这就是为什么处理大量数据会很困难。确保你只保留必要的数据,其他的就不要了。
如果这个矩阵大部分都是空的,我建议你看看一些稀疏矩阵的库。SciPy和NumPy是最常用的,但我相信还有其他人提供适合Python 2.3的解决方案。也许可以找找旧版的NumPy?
使用Python 2.3会限制你的选择,比如你不能使用64位版本。这也是内存没有被释放回操作系统的主要原因:在CPython中,内部的对象分配器直到2.5版本才有能力把不再使用的内存还给操作系统。
如果可以的话,试着在2.7版本上运行你的算法,看看使用更新的解释器版本能带来什么好处(或者在迁移过程中可能会遇到什么兼容性问题)。
另外,正如其他人所建议的,优化你的数据结构。检查你经常执行的操作的算法复杂度,看看有没有办法把O(n*n)的操作转换为O(n*logn),把O(n)转换为O(logn)或O(1)。
即使底层的数据结构不能改变,你也可以尝试使用bisect
模块来加速一些列表操作。
你可以试试 array
模块,它在 Python 2.3 就已经有了。除此之外,你可能还想考虑使用一个合适的数据库来处理这些数据。