65

我正在寻找一种简单的方法来了解数组和字典对象的字节大小,例如

[ [1,2,3], [4,5,6] ] or { 1:{2:2} }

许多主题都说要使用 pylab,例如:

from pylab import *

A = array( [ [1,2,3], [4,5,6] ] )
A.nbytes
24

但是,字典呢?我看到很多建议使用 pysize 或 heapy 的答案。Torsten Marek 在此链接中给出了一个简单的答案:推荐使用哪种 Python 内存分析器?,但我对输出没有明确的解释,因为字节数不匹配。

Pysize 似乎更复杂,我还不清楚如何使用它。

鉴于我想要执行的大小计算的简单性(没有类也没有复杂的结构),有什么简单的方法可以大致估计此类对象的内存使用情况吗?

亲切的问候。

4

7 回答 7

63

有:

>>> import sys
>>> sys.getsizeof([1,2, 3])
96
>>> a = []
>>> sys.getsizeof(a)
72
>>> a = [1]
>>> sys.getsizeof(a)
80

但我不会说它那么可靠,因为 Python 对每个对象都有开销,并且有些对象只包含对其他对象的引用,因此它与 C 和其他语言中的不太一样。

阅读sys.getsizeof上的文档并从那里开始我猜。

于 2012-11-23T14:13:11.813 回答
53

这里没有一个答案是真正通用的。

以下解决方案将递归地处理任何类型的对象,而不需要昂贵的递归实现:

import gc
import sys

def get_obj_size(obj):
    marked = {id(obj)}
    obj_q = [obj]
    sz = 0

    while obj_q:
        sz += sum(map(sys.getsizeof, obj_q))

        # Lookup all the object referred to by the object in obj_q.
        # See: https://docs.python.org/3.7/library/gc.html#gc.get_referents
        all_refr = ((id(o), o) for o in gc.get_referents(*obj_q))

        # Filter object that are already marked.
        # Using dict notation will prevent repeated objects.
        new_refr = {o_id: o for o_id, o in all_refr if o_id not in marked and not isinstance(o, type)}

        # The new obj_q will be the ones that were not marked,
        # and we will update marked with their ids so we will
        # not traverse them again.
        obj_q = new_refr.values()
        marked.update(new_refr.keys())

    return sz

例如:

>>> import numpy as np
>>> x = np.random.rand(1024).astype(np.float64)
>>> y = np.random.rand(1024).astype(np.float64)
>>> a = {'x': x, 'y': y}
>>> get_obj_size(a)
16816

请参阅我的存储库以获取更多信息,或者简单地安装我的包(objsize):

$ pip install objsize

然后:

>>> from objsize import get_deep_size
>>> get_deep_size(a)
16816
于 2018-12-10T12:24:29.807 回答
32

派对有点晚了,但获得 dict 大小的一个简单方法是先腌制它。

在 python 对象(包括字典)上使用 sys.getsizeof 可能不准确,因为它不计算引用的对象。

处理它的方法是将其序列化为字符串并在字符串上使用 sys.getsizeof 。结果会更接近你想要的。

import cPickle

mydict = {'key1':'some long string, 'key2':[some, list], 'key3': whatever other data}

做 sys.getsizeof(mydict) 不准确,先腌制

mydict_as_string = cPickle.dumps(mydict)

现在我们可以知道它需要多少空间

print sys.getsizeof(mydict_as_string)
于 2013-05-15T19:42:24.050 回答
13

使用这个食谱,取自这里:

http://code.activestate.com/recipes/577504-compute-memory-footprint-of-an-object-and-its-cont/

from __future__ import print_function
from sys import getsizeof, stderr
from itertools import chain
from collections import deque
try:
    from reprlib import repr
except ImportError:
    pass

def total_size(o, handlers={}, verbose=False):
    """ Returns the approximate memory footprint an object and all of its contents.

    Automatically finds the contents of the following builtin containers and
    their subclasses:  tuple, list, deque, dict, set and frozenset.
    To search other containers, add handlers to iterate over their contents:

        handlers = {SomeContainerClass: iter,
                    OtherContainerClass: OtherContainerClass.get_elements}

    """
    dict_handler = lambda d: chain.from_iterable(d.items())
    all_handlers = {tuple: iter,
                    list: iter,
                    deque: iter,
                    dict: dict_handler,
                    set: iter,
                    frozenset: iter,
                   }
    all_handlers.update(handlers)     # user handlers take precedence
    seen = set()                      # track which object id's have already been seen
    default_size = getsizeof(0)       # estimate sizeof object without __sizeof__

    def sizeof(o):
        if id(o) in seen:       # do not double count the same object
            return 0
        seen.add(id(o))
        s = getsizeof(o, default_size)

        if verbose:
            print(s, type(o), repr(o), file=stderr)

        for typ, handler in all_handlers.items():
            if isinstance(o, typ):
                s += sum(map(sizeof, handler(o)))
                break
        return s

    return sizeof(o)


##### Example call #####

if __name__ == '__main__':
    d = dict(a=1, b=2, c=3, d=[4,5,6,7], e='a string of chars')
    print(total_size(d, verbose=True))
于 2016-02-03T08:57:46.120 回答
2

我刚刚从另一个问题中了解到,模块pymler比 sys.getsizeof 更适合自创对象。只需按如下方式使用它:

from pympler import asizeof
asizeof.asizeof(my_object)
于 2020-01-14T10:47:32.840 回答
2

我正在寻找一种方法,该方法将返回与该精确多维数组(56x56x128)的保存文件相同的大小。我终于使用了这种方法,它给了我文件使用的相同内存大小:

import numpy as np
my_list = np.random.rand(56,56,128)
print(my_list.nbytes) #/1000 => KB, /1000000 => MB and /1000000000 => GB
np.save("my_list.npy",my_list) # my_list.npy size is: 3.2 MB
于 2020-08-02T14:35:53.900 回答
1

如果您想测量您将通过例如发送的身体的大小。HTTP作为JSON,你能不能先把它转换成str,然后计算它的长度?毕竟,您将其作为文本发送。所以这:

>>> import json
>>> import sys

>>> my_dict = {"var1": 12345, "var2": "abcde", "var3": 23.43232, "var4": True, "var5": None}
>>> a = json.dumps(my_dict)

>>> len(a)
78
>>> sys.getsizeof(my_dict)
232
>>> sys.getsizeof(a)
127

转换后的对象中的字符总数为 78,因此在 1 个字符 = 1 个字节的计算机中,78 个字节将是合理的答案,并且似乎比使用sys.getsizeof.

于 2021-09-30T07:21:52.497 回答