Python结构的内存占用大小

142 投票
7 回答
130351 浏览
提问于 2025-04-15 13:52

有没有关于Python数据结构在32位和64位平台上内存大小的参考资料?

如果没有的话,这个信息在Stack Overflow上会很有用。越详细越好!那么以下这些Python结构大概占用多少字节呢(根据len和内容类型的不同)?

  • int(整数)
  • float(浮点数)
  • 引用
  • str(字符串)
  • unicode字符串
  • tuple(元组)
  • list(列表)
  • dict(字典)
  • set(集合)
  • array.array(数组)
  • numpy.array(NumPy数组)
  • deque(双端队列)
  • 新式类对象
  • 旧式类对象
  • ... 还有我忘记的其他所有东西!

(对于那些只保存其他对象引用的容器,我们显然不想计算它们所包含项的大小,因为这些项可能是共享的。)

此外,有没有办法在运行时获取一个对象所占用的内存(可以是递归的,也可以不是)?

7 个回答

39

我一直很高兴地使用pympler来完成这类任务。它支持很多版本的Python,特别是里面的asizeof模块,甚至可以追溯到2.2版本!

比如,使用hughdbrown的例子,只需在开头加上from pympler import asizeof,在最后加上print asizeof.asizeof(v),我在MacOSX 10.5上使用系统自带的Python 2.5时看到的结果是:

$ python pymp.py 
set 120
unicode 32
tuple 32
int 16
decimal 152
float 16
list 40
object 0
dict 144
str 32

显然这里有一些近似值,但我发现它在分析程序占用空间和优化方面非常有用。

60

这些回答都只是收集了一些表面的大小信息。我猜这里来的人可能想知道“这个复杂的对象在内存中占多大?”

这里有一个很好的答案: https://goshippo.com/blog/measure-real-size-any-python-object/

重点是:

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

用法如下:

In [1]: get_size(1)
Out[1]: 24

In [2]: get_size([1])
Out[2]: 104

In [3]: get_size([[1]])
Out[3]: 184

如果你想更深入了解Python的内存模型,这里有一篇很棒的文章,里面有类似的“总大小”代码片段,作为更长解释的一部分: https://code.tutsplus.com/tutorials/understand-how-much-memory-your-python-objects-use--cms-25609

167

之前有个问题提到,想要知道一个对象的大小,可以使用 sys.getsizeof() 这个方法,引用如下:

>>> import sys
>>> x = 2
>>> sys.getsizeof(x)
14
>>> sys.getsizeof(sys.getsizeof)
32
>>> sys.getsizeof('this')
38
>>> sys.getsizeof('this also')
48

你可以这样做:

>>> import sys
>>> import decimal
>>> 
>>> d = {
...     "int": 0,
...     "float": 0.0,
...     "dict": dict(),
...     "set": set(),
...     "tuple": tuple(),
...     "list": list(),
...     "str": "a",
...     "unicode": u"a",
...     "decimal": decimal.Decimal(0),
...     "object": object(),
... }
>>> for k, v in sorted(d.iteritems()):
...     print k, sys.getsizeof(v)
...
decimal 40
dict 140
float 16
int 12
list 36
object 8
set 116
str 25
tuple 28
unicode 28

2012年9月30日

python 2.7(在linux上,32位):

decimal 36
dict 136
float 16
int 12
list 32
object 8
set 112
str 22
tuple 24
unicode 32

python 3.3(在linux上,32位):

decimal 52
dict 144
float 16
int 14
list 32
object 8
set 112
str 26
tuple 24
unicode 26

2016年8月1日

在OSX上,Python 2.7.10(默认版本,2015年10月23日,19:19:21)[GCC 4.2.1 兼容 Apple LLVM 7.0.0 (clang-700.0.59.5) ] 在darwin系统上运行

decimal 80
dict 280
float 24
int 24
list 72
object 16
set 232
str 38
tuple 56
unicode 52

撰写回答