没有什么内存问题,是一行Python代码解决不了的

作者:媒体转发 时间:2018-12-18 16:37

字号

Python代码

大数据文摘出品

编译:Javen、胡笳、云舟

内存不足是项目开发过程中经常碰到的问题,我和我的团队在之前的一个项目中也遇到了这个问题,我们的项目需要存储和处理一个相当大的动态列表,测试人员经常向我抱怨内存不足。但是最终,我们通过添加一行简单的代码解决了这个问题。

结果如图所示:

Python代码

我将在下面解释它的工作原理。

举一个简单的“learning”示例 - 创建一个DataItem类,在其中定义一些个人信息属性,例如姓名,年龄和地址。

class DataItem(object): 

   def __init__(self, name, age, address): 

       self.name = name 

       self.age = age 

       self.address = address 

小测试——这样一个对象会占用多少内存?

首先让我们尝试下面这种测试方案:

d1 = DataItem("Alex", 42, "-") 

print ("sys.getsizeof(d1):", sys.getsizeof(d1)) 

答案是56字节。看起来比较小,结果令人满意。

但是,让我们检查另一个数据多一些的对象:

d2 = DataItem("Boris", 24, "In the middle of nowhere") 

print ("sys.getsizeof(d2):", sys.getsizeof(d2)) 

答案仍然是56。这让我们明白这个结果并不完全正确。

我们的直觉是对的,这个问题不是那么简单。Python是一种非常灵活的语言,具有动态类型,它在工作时存储了许多额外的数据。这些额外的数据本身就占了很多内存。

例如,sys.getsizeof(“ ”)返回33,没错,每个空行就多达33字节!并且sys.getsizeof(1)将为此数字返回24-24个字节(我建议C程序员们现在点击结束阅读,以免对Python的美丽失去信心)。

对于更复杂的元素,例如字典,sys.getsizeof(dict())返回272个字节,这还只是一个空字典。举例到此为止,但事实已经很清楚了,何况RAM的制造商也需要出售他们的芯片。

现在,让我们回到回到我们的DataItem类和“小测试”问题。

这个类到底占多少内存?

首先,我们将以较低级别输出该类的全部内容:

def dump(obj): 

 for attr in dir(obj): 

   print("  obj.%s = %r" % (attr, getattr(obj, attr))) 

这个函数将显示隐藏在“隐身衣”下的内容,以便所有Python函数(类型,继承和其他包)都可以运行。

结果令人印象深刻:

没有什么内存问题,是一行Python代码解决不了的

它总共占用多少内存呢?

在GitHub上,有一个函数可以计算实际大小,通过递归调用所有对象的getsizeof实现。

def get_size(obj, seen=None): 

   # From https://goshippo.com/blog/measure-real-size-any-python-object/ 

   # Recursively finds size of objects 

   size = sys.getsizeof(obj) 

   if seen is None: 

       seen = set() 

   obj_id = id(obj) 

   if obj_id in seen: 

       return 0 

 

# Important mark as seen *before* entering recursion to gracefully handle 

   # self-referential objects 

   seen.add(obj_id) 

   if isinstance(obj, dict): 

     size += sum([get_size(v, seen) for v in obj.values()]) 

     size += sum([get_size(k, seen) for k in obj.keys()]) 

   elif hasattr(obj, '__dict__'): 

     size += get_size(obj.__dict__, seen) 

   elif hasattr(obj, '__iter__') and not isinstance(obj, (str, bytes, bytearray)): 

     size += sum([get_size(i, seen) for i in obj]) 

   return size 

让我们试一下:

d1 = DataItem("Alex", 42, "-") 

print ("get_size(d1):", get_size(d1)) 

 

d2 = DataItem("Boris", 24, "In the middle of nowhere") 

print ("get_size(d2):", get_size(d2)) 

我们分别得到460和484字节,这似乎更接近事实。

使用这个函数,我们可以进行一系列实验。例如,我想知道如果DataItem放在列表中,数据将占用多少空间。

责任编辑:CQITer新闻报料:400-888-8888   本站原创,未经授权不得转载
关键词 >>Python 代码 内存
继续阅读
热新闻
推荐
关于我们联系我们免责声明隐私政策 友情链接