web-dev-qa-db-ja.com

python配列や辞書のようなオブジェクトのバイトサイズを知る方法?-簡単な方法

私は配列と辞書オブジェクトのバイトサイズを知る簡単な方法を探していました

[ [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による簡単な答えが示されています。 Which Python memory profilerを推奨しますか? 、ただし、バイトのバイトが一致しませんでした。

Pysizeはもっと複雑であるように思われ、私はまだそれをどのように使うかについて明確な考えを持っていません。

実行したいサイズ計算の単純さ(クラスも複雑な構造もない)を考えると、この種のオブジェクトのメモリ使用量のおおよその見積もりを取得する簡単な方法についてのアイデアはありますか?

敬具。

40
crandrades

あります:

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

しかし、Pythonは各オブジェクトにオーバーヘッドがあり、他のオブジェクトへの参照のみを含むオブジェクトがあるため、Cおよび他の言語。

sys.getsizeof のドキュメントを読んで、そこから行くと思います。

49
Jon Clements

パーティーに少し遅れましたが、辞書のサイズを取得する簡単な方法は、最初にピクルスにすることです。

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)
27
Denis Kanygin

ここでの答えはどれも本当に一般的なものではありません。

次のソリューションは、高価な再帰的な実装を必要とせずに、あらゆるタイプのオブジェクトで再帰的に機能します。

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

詳細については my repository を参照するか、単にパッケージをインストールしてください( objsize ):

$ pip install objsize

次に:

>>> from objsize import get_deep_size
>>> get_deep_size(a)
16816
17
Liran Funaro

ここから取ったこのレシピを使用してください:

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 __== '__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))
12
Oren