如何在Python中获得对象在内存中占用的大小?


当前回答

我自己也遇到过很多次这个问题,我写了一个小函数(受到@aaron-hall的回答的启发)和测试,它完成了我所期望的sys。Getsizeof to do:

https://github.com/bosswissam/pysize

如果你对背景故事感兴趣,这就是

编辑:附上下面的代码以方便参考。要查看最新的代码,请检查github链接。

    import sys

    def get_size(obj, seen=None):
        """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

其他回答

如果不想包含链接(嵌套)对象的大小,请使用sys.getsizeof()。

然而,如果你想计算嵌套在列表、字典、集、元组中的子对象——通常这就是你要找的——使用如下所示的递归深层sizeof()函数:

import sys
def sizeof(obj):
    size = sys.getsizeof(obj)
    if isinstance(obj, dict): return size + sum(map(sizeof, obj.keys())) + sum(map(sizeof, obj.values()))
    if isinstance(obj, (list, tuple, set, frozenset)): return size + sum(map(sizeof, obj))
    return size

你也可以在漂亮的工具箱中找到这个函数,以及许多其他有用的一行程序:

https://github.com/mwojnars/nifty/blob/master/util.py

如果性能不是问题,最简单的解决方案是pickle和测量:

import pickle

data = ...
len(pickle.dumps(data))

我用这个技巧…May在小对象上不准确,但我认为对于复杂对象(如pygame surface)比sys.getsizeof()更准确。

import pygame as pg
import os
import psutil
import time


process = psutil.Process(os.getpid())
pg.init()    
vocab = ['hello', 'me', 'you', 'she', 'he', 'they', 'we',
         'should', 'why?', 'necessarily', 'do', 'that']

font = pg.font.SysFont("monospace", 100, True)

dct = {}

newMem = process.memory_info().rss  # don't mind this line
Str = f'store ' + f'Nothing \tsurface use about '.expandtabs(15) + \
      f'0\t bytes'.expandtabs(9)  # don't mind this assignment too

usedMem = process.memory_info().rss

for word in vocab:
    dct[word] = font.render(word, True, pg.Color("#000000"))

    time.sleep(0.1)  # wait a moment

    # get total used memory of this script:
    newMem = process.memory_info().rss
    Str = f'store ' + f'{word}\tsurface use about '.expandtabs(15) + \
          f'{newMem - usedMem}\t bytes'.expandtabs(9)

    print(Str)
    usedMem = newMem

在我的windows 10, python 3.7.3,输出是:

store hello          surface use about 225280    bytes
store me             surface use about 61440     bytes
store you            surface use about 94208     bytes
store she            surface use about 81920     bytes
store he             surface use about 53248     bytes
store they           surface use about 114688    bytes
store we             surface use about 57344     bytes
store should         surface use about 172032    bytes
store why?           surface use about 110592    bytes
store necessarily    surface use about 311296    bytes
store do             surface use about 57344     bytes
store that           surface use about 110592    bytes

下面是我根据之前对所有变量的列表大小的回答编写的一个快速脚本

for i in dir():
    print (i, sys.getsizeof(eval(i)) )

你可以序列化对象,以获得与对象大小密切相关的度量值:

import pickle

## let o be the object whose size you want to measure
size_estimate = len(pickle.dumps(o))

如果您想测量无法pickle的对象(例如,由于lambda表达式),dill或cloudpickle可以是一种解决方案。