如何估算一个Python对象的如何查看电脑内存占用用

博客分类:
python对象内存分析
一、python内建对象
python内建对象占用内存的情况又分为定长对象与非定长对象(变长)
1.1 定长对象,对象在内存中所占大小不会变化的对象
包括int,float,long,bool,complex和dict
测试程序如下:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import sys
print "value\t\ttype\t\tmemsize"
alist=[0,1,10,-1,-444,12313]
for i in alist:
print "%d\t\t%s\t\t%s"%(i,type(i),sys.getsizeof(i))
#float test
blist=[0.0,1.0,111.1,.1]
for i in blist:
print "%f\t\t%s\t\t%s"%(i,type(i),sys.getsizeof(i))
#long test
clist=[0l,1l,2l,-l]
for i in clist:
print "%d\t\t%s\t\t%s"%(i,type(i),sys.getsizeof(i))
#bool test
dlist=[True,False]
for i in dlist:
print "%s\t\t%s\t\t%s"%(i,type(i),sys.getsizeof(i))
#complex test
elist=[0j,1+0j,1+1j,1000-23j,-100+5j]
for i in elist:
print i,"\t\t%s\t\t%s"%(type(i),sys.getsizeof(i))
#dict test
flist=[{},{'a':'b'},{'a':'b','c':1},{'a':'b','c':1,'d':'你好'}]
for i in flist:
print i,"\t\t%s\t\t%s"%(type(i),sys.getsizeof(i))
运行结果如下:
&type 'int'&
&type 'int'&
&type 'int'&
&type 'int'&
&type 'int'&
&type 'int'&
&type 'float'&
&type 'float'&
111.100000
&type 'float'&
&type 'float'&
&type 'float'&
&type 'long'&
&type 'long'&
&type 'long'&
&type 'long'&
&type 'long'&
&type 'bool'&
&type 'bool'&
&type 'complex'&
&type 'complex'&
&type 'complex'&
(1000-23j)
&type 'complex'&
&type 'complex'&
&type 'dict'&
{'a': 'b'}
&type 'dict'&
{'a': 'b', 'c': 1}
&type 'dict'&
{'a': 'b', 'c': 1, 'd': '\xe4\xbd\xa0\xe5\xa5\xbd'}
&type 'dict'&
有运行结果可以看出各个定长对象所占的内存:
int和float:24
long:这个有点特殊,对于0l,python识别为long type,但是所占内存是24,除了0l所占内存为24以外,其他的都为28
complex(复数):32
dict(字典):280
1.2 变成对象,会随着对象变化所占用的内存会变化
包括:list,tuple,str
测试代码:
#/usr/bin/env python
#-*- coding: utf-8 -*-
import sys
print "str-length\ttype\tmemsize"
ga=ua.decode('utf-8').encode('gbk')
ba=ua.decode('utf-8').encode('big5')
ga1=ua.decode('utf-8').encode('gb2312')
alist=['','a','ab',ua,ga,ba,ga1]
for s in alist:
print "%d\t%s\t%s"%(len(s),type(s),sys.getsizeof(s))
print "list-length\ttype\tmemsize"
#list test
alist=[[],['a','b'],['abc','你好'],[11,12,'eee']]
for li in alist:
print "%d\t%s\t%s"%(len(li),type(li),sys.getsizeof(li))
print "%d\t%s\t%s"%(len(alist),type(alist),sys.getsizeof(alist))
#tuple test
print "tuple-len\ttype\tmemsize"
alist=((),('a',),('abc','你好'),(11,12,'eeee'))
for tp in alist:
print "%d\t%s\t%s"%(len(tp),type(tp),sys.getsizeof(tp))
print "%d\t%s\t%s"%(len(alist),type(alist),sys.getsizeof(alist))
str-length type memsize
0 &type 'str'& 37
1 &type 'str'& 38
2 &type 'str'& 39
6 &type 'str'& 43
4 &type 'str'& 41
4 &type 'str'& 41
4 &type 'str'& 41
list-length type memsize
0 &type 'list'& 72
2 &type 'list'& 88
2 &type 'list'& 88
3 &type 'list'& 96
4 &type 'list'& 104
tuple-len type memsize
0 &type 'tuple'& 56
1 &type 'tuple'& 64
2 &type 'tuple'& 72
3 &type 'tuple'& 80
4 &type 'tuple'& 88
分析结果可知:
str:空str所占内存为37,若str长度每加1,则内存所占大小相应加1
list:空列表所占内存为72,长度每增加1,则所占内存加8
tuple:空元组所占内存为56,长度每加1,所占了内存加8
空字符串为什么是37,而不是36或38,因为这里介绍所有的对像内存都为偶数,python内部维护字符串的机制和C中维护字符串的机制是一样的,即在末尾加'\0',这个占了1个字节,所以内存大小表现为36+1=37
python中还有一个比较特殊的对象,就是类型对像
&&& tlist=(int,float,long,str,complex,dict,list,tuple,bool,type)
&&& for i in tlist:
print sys.getsizeof(i)
类型对象也是定长的为872
基类对象object所占内存也为872
二、自建对象
测试程序:
#!/usr/bin/env python
import sys
def __init__(self):
self.value=2
def test(self):
print self.value
class B(object):
def test(self):
print "test"
class C(float):
def __init__(self):
self.value=1
def test(self):
print self.value
class D(object):
class E(A):
:%s\t%s"%(type(A),sys.getsizeof(A))
print "A():%s\t%s"%(type(A()),sys.getsizeof(A()))
:%s\t%s"%(type(B),sys.getsizeof(B))
print "B():%s\t%s"%(type(B()),sys.getsizeof(B()))
:%s\t%s"%(type(C),sys.getsizeof(C))
print "C():%s\t%s"%(type(C()),sys.getsizeof(C()))
:%s\t%s"%(type(D),sys.getsizeof(D))
print "D():%s\t%s"%(type(D()),sys.getsizeof(D()))
:%s\t%s"%(type(E),sys.getsizeof(E))
print "E():%s\t%s"%(type(E()),sys.getsizeof(E()))
:&type 'classobj'& 104
A():&type 'instance'& 72
:&type 'type'& 904
B():&class '__main__.B'& 64
:&type 'type'& 904
C():&class '__main__.C'& 72
:&type 'type'& 904
D():&class '__main__.D'& 64
:&type 'classobj'& 104
E():&type 'instance'& 72
有结果可以看出:
A和E对象没有继承类型对象,未申明基类的情况下,类型python解释为’classobj',所占内存为104,实例化后类型为instance 内存为72
BD对象都是继承自基类object,类型为type,所占内存为904,实例化后类型为class,所占内存为64
C对象继承自类型对象 float,类型为type,所占内存为904,实例化后类型为class,所占内存为72
PS:object是所有对象的基类,python中所有对象都继承自object
浏览: 3109 次
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'内存占用减少高达90%,还不用升级硬件?没错,这篇文章教你妙用Pandas轻松处理大规模数据|内存|字符串|数据类型_新浪科技_新浪网
& 滚动新闻 &&正文
内存占用减少高达90%,还不用升级硬件?没错,这篇文章教你妙用Pandas轻松处理大规模数据
AI科技大本营
编译 | AI科技大本营(rgznai100)参与 | 周翔 注:Pandas(Python Data Analysis Library) 是基于 NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。此外,Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。相比较于 Numpy,Pandas 使用一个二维的数据结构 DataFrame 来表示表格式的数据, 可以存储混合的数据结构,同时使用 NaN 来表示缺失的数据,而不用像 Numpy 一样要手工处理缺失的数据,并且 Pandas 使用轴标签来表示行和列。Pandas 通常用于处理小数据(小于 100Mb),而且对计算机的性能要求不高,但是当我们需要处理更大的数据时(100Mb到几千Gb),计算机性能就成了问题,如果配置过低就会导致更长的运行时间,甚至因为内存不足导致运行失败。在处理大型数据集时(100Gb到几TB),我们通常会使用像 Spark 这样的工具,但是想要充分发挥 Spark 的功能,通常需要很高的硬件配置,导致成本过高。而且与 Pandas 不同,这些工具缺少可用于高质量数据清洗、勘测和分析的特征集。因此对于中等规模的数据,我们最好挖掘 Pandas 的潜能,而不是转而使用其他工具。那么在不升级计算机配置的前提下,我们要怎么解决内存不足的问题呢?在这篇文章中,我们将介绍 Pandas 的内存使用情况,以及如何通过为数据框(dataframe)中的列(column)选择适当的数据类型,将数据框的内存占用量减少近 90%。棒球比赛日志我们将要处理的是 130 年来的大型棒球联盟比赛数据,原始数据来源于 retrosheet。最原始的数据是 127 个独立的 CSV 文件,不过我们已经使用 csvkit 合并了这些文件,并且在第一行中为每一列添加了名字。如果读者想亲自动手操作,可下载网站上的数据实践下:https://data.world/dataquest/mlb-game-logs首先让我们导入数据,看看前五行:import pandas as pdgl = pd.read_csv('game_logs.csv')gl.head()我们总结了一些重要的列,但是如果你想查看所有的列的指南,我们也为整个数据集创建了一个数据字典:我们可以使用 () 的方法为我们提供数据框架的更多高层次的信息,包括数据大小、类型、内存使用情况的信息。默认情况下,Pandas 会占用和数据框大小差不多的内存来节省时间。因为我们对准确度感兴趣,所以我们将 memory_usage 的参数设置为 ‘deep’,以此来获取更准确的数字。我们可以看到,这个数据集共有 171,907 行、161 列。Pandas 已经自动检测了数据的类型:83 列数字(numeric),78 列对象(object)。对象列(object columns)主要用于存储字符串,包含混合数据类型。为了更好地了解怎样减少内存的使用量,让我们看看 Pandas 是如何将数据存储在内存中的。数据框的内部表示在底层,Pandas 按照数据类型将列分成不同的块(blocks)。这是 Pandas 如何存储数据框前十二列的预览。你会注意到这些数据块不会保留对列名的引用。这是因为数据块对存储数据框中的实际值进行了优化,BlockManager class 负责维护行、列索引与实际数据块之间的映射。它像一个 API 来提供访问底层数据的接口。每当我们选择、编辑、或删除某个值时,dataframe class 会和 BlockManager class 进行交互,将我们的请求转换为函数和方法调用。每个类型在 pandas.core.internals 模块中都有一个专门的类, Pandas 使用 ObjectBlock class 来代表包含字符串列的块,FloatBlock class 表示包含浮点型数据(float)列的块。对于表示数值(如整数和浮点数)的块,Pandas 将这些列组合在一起,并存储为 NumPy ndarry 数组。NumPy ndarry 是围绕 C array 构建的,而且它们的值被存储在连续的内存块中。由于采用这种存储方案,访问这些值的地址片段(slice)是非常快的。因为不同的数据都是单独存储的,所以我们将检查不同类型的数据的内存使用情况。我们先来看看所有数据类型的平均内存使用情况。可以看到,大部分的内存都被 78 个对象列占用了。我们稍后再来分析,首先看看我们是否可以提高数字列(numeric columns)的内存使用率。了解子类型正如前面介绍的那样,在底层,Pandas 将数值表示为 NumPy ndarrays,并将它存储在连续的内存块中。该存储模型消耗的空间较小,并允许我们快速访问这些值。因为 Pandas 中,相同类型的值会分配到相同的字节数,而 NumPy ndarray 里存储了值的数量,所以 Pandas 可以快速并准确地返回一个数值列占用的字节数。Pandas 中的许多类型包含了多个子类型,因此可以使用较少的字节数来表示每个值。例如,float 类型就包含 float16、float32、float64 等子类型。类型名称的数字部分代表了用于表示值类型的位数。例如,我们刚刚列出的子类型就分别使用了 2、4、8、16 个字节。下表显示了最常见的 Pandas 的子类型:int8 使用 1 个字节(或者 8 位)来存储一个值,并且可以以二进制表示 256 个值。这意味着,我们可以使用这种子类型来表示从 -128 到 127 (包括0)的值。我们可以使用 numpy.iinfo class 来验证每个整数子类型的最小值和最大值,我们来看一个例子:我们可以在这里看到 uint(无符号整数)和 int(有符号整数)之间的区别。这两种类型具有相同的存储容量,但如果只存储正数,无符号整数显然能够让我们更高效地存储只包含正值的列。使用子类型优化数字列我们可以使用函数 pd.to_numeric() 来 downcast(向下转型)我们的数值类型。我们将使用 DataFrame.select_dtypes 来选择整数列,然后优化这些列包含的类型,并比较优化前后内存的使用情况。我们可以看到,内存的使用量从 7.9Mb 降到了 1.5 Mb,减少了 80% 以上。但这对原始数据框的影响并不大,因为本身整数列就非常少。现在,让我们来对浮点型数列做同样的事情。可以看到,我们所有的浮点型数列都从 float64 转换成 float32,使得内存的使用量减少了 50%。让我们创建一个原始数据框的副本,然后分配这些优化后的数字列代替原始数据,并查看现在的内存使用情况。虽然我们大大减少了数字列的内存使用量,但是从整体来看,我们只是将数据框的内存使用量降低了 7%。内存使用量降低的主要原因是我们对对象类型(object types)进行了优化。在动手之前,让我们仔细看一下,与数字类型相比,字符串是怎样存在 Pandas 中的。比较数字和字符串的存储方式对象类型代表了 Python 字符串对象的值,部分原因是 NumPy 缺少对字符串值的支持。因为 Python 是一种高级的解释语言,它不能对数值的存储方式进行细粒度控制。这种限制使得字符串以分散的方式存储在内存里,不仅占用了更多的内存,而且访问速度较慢。对象列表中的每一个元素都是一个指针(pointer),它包含了实际值在内存中位置的“地址”。下面的图标展示了数字值是如何存储在 NumPy 数据类型中,以及字符串如何使用 Python 内置的类型存储。你可能已经注意到,我们的图表之前将对象类型描述成使用可变内存量。当每个指针占用一字节的内存时,每个字符的字符串值占用的内存量与 Python 中单独存储时相同。让我们使用 sys.getsizeof() 来自证明这一点:先查看单个字符串,然后查看 Pandas 系列中的项目(items)。你可以看到,存储在 Pandas 中的字符串的大小与作为 Python 中单独字符串的大小相同。使用分类来优化对象类型Pandas 在 0.15版引入了
Categoricals (分类)。category 类型在底层使用整数类型来表示该列的值,而不是原始值。Pandas 用一个单独的字典来映射整数值和相应的原始值之间的关系。当某一列包含的数值集有限时,这种设计是很有用的。当我们将列转换为 category dtype 时,Pandas 使用了最省空间的 int 子类型,来表示一列中所有的唯一值。想要知道我们可以怎样使用这种类型来减少内存使用量。首先 ,让我们看看每一种对象类型的唯一值的数量。可以看到,我们的数据集中一共有 17.2 万场比赛, 而唯一值的数量是非常少的。在我们深入分析之前,我们首先选择一个对象列,当我们将其转换为 categorical type时,观察下会发生什么。我们选择了数据集中的第二列 day_of_week 来进行试验。在上面的表格中,我们可以看到它只包含了七个唯一的值。我们将使用 .astype() 的方法将其转换为 categorical。如你所见,除了列的类型已经改变,这些数据看起来完全一样。我们来看看发生了什么。在下面的代码中,我们使用 Series.cat.codes 属性来返回 category 类型用来表示每个值的整数值。你可以看到,每个唯一值都被分配了一个整数,并且该列的底层数据类型现在是 int8。该列没有任何缺失值,如果有的话,这个 category 子类型会将缺省值设置为 -1。最后,我们来看看这个列在转换到 category 类型之前和之后的内存使用情况。可以看到,内存使用量从原来的 9.8MB 降到了 0.16MB,相当于减少了 98%!请注意,这一列可能代表我们最好的情况之一:一个具有 172,000 个项目的列,只有 7 个唯一的值。将所有的列都进行同样的操作,这听起来很吸引人,但使我们要注意权衡。可能出现的最大问题是无法进行数值计算。我们不能在将其转换成真正的数字类型的前提下,对这些 category 列进行计算,或者使用类似 Series.min() 和 Series.max() 的方法。当对象列中少于 50% 的值时唯一对象时,我们应该坚持使用 category 类型。但是如果这一列中所有的值都是唯一的,那么 category 类型最终将占用更多的内存。这是因为列不仅要存储整数 category 代码,还要存储所有的原始字符串的值。你可以阅读 Pandas 文档,了解 category 类型的更多限制。我们将编写一个循环程序,遍历每个对象列,检查其唯一值的数量是否小于 50%。如果是,那么我们就将这一列转换为 category 类型。和之前的相比在这种情况下,我们将所有对象列都转换为 category 类型,但是这种情况并不符合所有的数据集,因此务必确保事先进行过检查。此外,对象列的内存使用量已经从 752MB 将至 52MB,减少了 93%。现在,我们将其与数据框的其余部分结合起来,再与我们最开始的 861MB 的内存使用量进行对比。可以看到,我们已经取得了一些进展,但是我们还有一个地方可以优化。回到我们的类型表,里面有一个日期(datetime)类型可以用来表示数据集的第一列。你可能记得这一列之前是作为整数型读取的,而且已经被优化为 uint32。因此,将其转换为 datetime 时,内存的占用量会增加一倍,因为 datetime 的类型是 64 位。无论如何,将其转换成 datetime 是有价值的,因为它将让时间序列分析更加容易。我们将使用 pandas.to_datetime()
函数进行转换,并使用 format 参数让日期数据按照
YYYY-MM-DD 的格式存储。在读取数据时选择类型到目前为止,我们已经探索了减少现有数据框内存占用的方法。首先,读入阅读数据框,然后再反复迭代节省内存的方法,这让我们可以更好地了解每次优化可以节省的内存空间。然而,正如我们前面提到那样,我们经常没有足够的内存来表示数据集中所有的值。如果一开始就不能创建数据框,那么我们该怎样使用内存节省技术呢?幸运的是,当我们读取数据集时,我们可以制定列的最优类型。pandas.read_csv() 函数有几个不同的参数可以让我们做到这一点。dtype 参数可以是一个以(字符串)列名称作为 keys、以 NumPy 类型对象作为值的字典。首先,我们将每列的最终类型、以及列的名字的 keys 存在一个字典中。因为日期列需要单独对待,因此我们先要删除这一列。现在,我们可以使用字典、以及几个日期的参数,通过几行代码,以正确的类型读取日期数据。通过优化这些列,我们设法将 pandas 中的内存使用量,从 861.6MB 降到了 104.28MB,减少了 88%。分析棒球比赛我们已经优化了数据,现在我们可以开始对数据进行分析了。我们来看看比赛的时间分布。可以看到,在二十世纪二十年代之前,棒球比赛很少在周日举行,一直到下半世纪才逐渐流行起来。此外,我们也可以清楚地看到,在过去的五十年里,比赛时间的分是相对静态的。我们来看看比赛时长多年来的变化。看起来,棒球比赛的时长自 1940 年以来就一直处于增长状态。总结和后续步骤我们已经了解到 Pandas 是如何存储不同类型的数据的,然后我们使用这些知识将 Pandas 里的数据框的内存使用量降低了近 90%,而这一切只需要几个简单的技巧:将数字列 downcast 到更节省空间的类型;将字符串转换为分类类型(categorical type)。你,学会了吗?原文地址https://www.dataquest.io/blog/pandas-big-data/【本文来自投稿,文中观点不代表Xtecher立场。】
或许谁都不希望看到这样一个景象,不久的将来搭载Helio X30的某某...
腾讯在资本市场受此影响依然很是明显,7月4日,腾讯控股跌幅达4....
近日一款名为“全能车”软件受到人们关注,只要缴纳一份押金,便...&写一个脚本计算一下所有进程所占用内存大小的和。(提示,使用ps aux 列出所有进程,过滤出RSS那列,然后求和)
#!/usr/bin/env python
#!coding=utf-<span style="color: #
sum = <span style="color: #
str1 = os.popen('ps aux','r').readlines()
for i in str1:
str2 = i.split()
new_rss = str2[<span style="color: #]
//rss为第五列
list.append(new_rss)
list[<span style="color: #:-<span style="color: #]:
num = int(i)
sum = sum + num
print '%s:%s' %(list[<span style="color: #],sum)
附:ps auxroot  PID   CPU  MEM  RSS  TTY  SATA  START  TIME  COMMAND
阅读(...) 评论()

我要回帖

更多关于 如何清理内存占用 的文章

 

随机推荐