Python-如何显示所有变量的大小

82

我想同时打印出我的作用域中所有变量的内存大小。

类似于这样:

for obj in locals().values():
    print sys.getsizeof(obj)
但是在每个值之前添加变量名称,以便我可以看到需要删除或分批拆分哪些变量。有什么想法?
3个回答

133

再多写一点代码,但适用于Python 3,并提供了一个排序的、易读的输出:

import sys
def sizeof_fmt(num, suffix='B'):
    ''' by Fred Cirera,  https://dev59.com/unNA5IYBdhLWcg3wF5uO#1094933, modified'''
    for unit in ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi']:
        if abs(num) < 1024.0:
            return "%3.1f %s%s" % (num, unit, suffix)
        num /= 1024.0
    return "%.1f %s%s" % (num, 'Yi', suffix)

for name, size in sorted(((name, sys.getsizeof(value)) for name, value in list(
                          locals().items())), key= lambda x: -x[1])[:10]:
    print("{:>30}: {:>8}".format(name, sizeof_fmt(size)))

示例输出:

                  umis:   3.6 GiB
       barcodes_sorted:   3.6 GiB
          barcodes_idx:   3.6 GiB
              barcodes:   3.6 GiB
                  cbcs:   3.6 GiB
         reads_per_umi:   1.3 GiB
          umis_per_cbc:  59.1 MiB
         reads_per_cbc:  59.1 MiB
                   _40:  12.1 KiB
                     _:   1.6 KiB

请注意,此操作仅会打印出前10个最大的变量,并且对于其余的变量将保持沉默。如果你真的想要打印全部变量,请从倒数第二行移除[:10]


不错!你能解释一下这些“_40”是什么吗?对我来说,它显示了多个“_\d+”行。有些看起来像命名变量一样大小完全相同,而其他的则不同。 - MoRe
3
@MoRe 这些(可能是)暂时性的变量承载着 Jupyter Notebook 单元格的输出。请参阅文档 - jan-glx
这段代码非常有用,尽管我的变量总共约为5.1 GB,但根据resource.getrusage的内存使用情况大约为10.9 GB。这是在Google Colab中的情况。还有什么可能占用了其余的内存? - demongolem
1
@gocen:是的。6340200200个双精度浮点数*64位/双精度浮点数 /(8位/字节)/(2 ^ 30字节每GB)= 1.889 GB - jan-glx
1
当运行上述代码时,我遇到了“字典在迭代过程中改变了大小”的问题。这里是一个先导出到列表的修改版:import sys def sizeof_fmt(num, suffix='B'): ... (由于字符限制而被截断) local_vars = list(locals().items()) variables = [(var, (sys.getsizeof(obj))) for var, obj in local_vars] variables = sorted(((var, size_value) for var, size_value in variables), key= lambda x: -x[1]) variables = [(var, sizeof_fmt(size_value)) for var, size_value in variables] for var, size_fmt in variables[:10]: print("{:>30}: {:>8}".format(var, size_fmt)) - SJGD
显示剩余9条评论

73

使用 .items() 可以同时迭代字典的键和值。

from __future__ import print_function  # for Python2
import sys

local_vars = list(locals().items())
for var, obj in local_vars:
    print(var, sys.getsizeof(obj))

3
这导致了 RuntimeError: 在迭代过程中字典大小发生了变化。 - Pradeep Singh
使用 local_vars = list(locals().items()) 可以避免 RuntimeError。 - TomDLT
7
如果有人想知道尺寸的单位是什么:它是 **字节(Bytes)**。sys.getsizeof() - xanjay

0

我发现对于某些容器,我没有得到正确的答案(仅限开销?)。
将@jan_Glx上面的答案与下面帖子中的片段结合起来
如何知道Python对象(如数组和字典)的字节大小?-简单方法

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

def sizeof_fmt(num, suffix='B'):
    ''' by Fred Cirera,  https://dev59.com/unNA5IYBdhLWcg3wF5uO#1094933, modified'''
    for unit in ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi']:
        if abs(num) < 1024.0:
            return "%3.1f %s%s" % (num, unit, suffix)
        num /= 1024.0
    return "%.1f %s%s" % (num, 'Yi', suffix)

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 #####

for name, size in sorted(((name, total_size(value, verbose=False)) for name, value in list(
                          locals().items())), key= lambda x: -x[1])[:20]:
    print("{:>30}: {:>8}".format(name, sizeof_fmt(size)))

    

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接