मैं पायथन में किसी वस्तु का आकार कैसे निर्धारित करूं?


683

मैं जानना चाहता हूं कि पायथन में एक स्ट्रिंग, पूर्णांक, आदि जैसी वस्तुओं का आकार कैसे प्राप्त किया जाए।

संबंधित प्रश्न: पायथन सूची (टपल) में प्रति तत्व कितने बाइट होते हैं?

मैं एक XML फ़ाइल का उपयोग कर रहा हूं जिसमें आकार फ़ील्ड हैं जो मूल्य के आकार को निर्दिष्ट करते हैं। मुझे इस XML को पार्स करना चाहिए और अपनी कोडिंग करनी चाहिए। जब मैं किसी विशेष क्षेत्र के मूल्य को बदलना चाहता हूं, तो मैं उस मूल्य के आकार क्षेत्र की जांच करूंगा। यहां मैं तुलना करना चाहता हूं कि क्या मैं जिस नए मूल्य में प्रवेश करने के लिए हूं, वह उसी आकार का है जैसा एक्सएमएल में है। मुझे नए मूल्य के आकार की जांच करने की आवश्यकता है। एक स्ट्रिंग के मामले में मैं इसकी लंबाई कह सकता हूं। लेकिन इंट, फ्लोट आदि के मामले में मैं भ्रमित हूं।

जवाबों:


665

बस मॉड्यूल में परिभाषित sys.getizeof फ़ंक्शन का उपयोग करें sys

sys.getsizeof(object[, default]):

किसी वस्तु का आकार बाइट्स में लौटाएं। वस्तु किसी भी प्रकार की वस्तु हो सकती है। सभी अंतर्निहित वस्तुएँ सही परिणाम लौटाएंगी, लेकिन इसे तीसरे पक्ष के एक्सटेंशन के लिए सही नहीं रखना होगा क्योंकि यह विशिष्ट है।

defaultतर्क एक मूल्य के जो करता है, तो ऑब्जेक्ट प्रकार आकार पुनः प्राप्त करने के साधन प्रदान नहीं करता है और एक कारण होगा लौटा दी जाएगी परिभाषित करने के लिए अनुमति देता है TypeError

getsizeofऑब्जेक्ट की __sizeof__विधि को कॉल करता है और अतिरिक्त कचरा कलेक्टर ओवरहेड जोड़ता है यदि ऑब्जेक्ट को कचरा कलेक्टर द्वारा प्रबंधित किया जाता है।

उदाहरण उदाहरण, अजगर 3.0 में:

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

यदि आप अजगर <2.6 में हैं और sys.getsizeofआपके पास इस व्यापक मॉड्यूल का उपयोग नहीं कर सकते हैं । हालांकि इसका इस्तेमाल कभी नहीं किया।


181
कृपया डिस्क्लेमर में जोड़ें कि यह नेस्टेड ऑब्जेक्ट्स या नेस्टेड डक्ट्स या
डीकट्स

8
@ChaimG इसलिए कि हर वस्तु केवल 32 बाइट्स का उपयोग करती है !! बाकी अन्य वस्तुओं के संदर्भ हैं। यदि आप संदर्भित वस्तुओं का हिसाब चाहते हैं तो आपको __sizeof__अपनी कक्षा के लिए विधि निर्धारित करनी होगी । अंतर्निहित dictअजगर वर्ग इसे परिभाषित करता है, इसीलिए आपको ऑब्जेक्ट के प्रकार का उपयोग करते समय सही परिणाम मिलता है dict
nosklo

19
इस काम के कवर के लिए अस्वीकरण और अपवाद लगभग सभी उपयोग के मामले getsizeofहैं जो बॉक्स से थोड़ा मूल्य का कार्य करते हैं।
रॉबिनो

7
पूर्णांक 2 को 24 बाइट्स में क्यों संग्रहीत किया जाता है?
साहेर अहवाल

4
@SaherAhwal यह केवल एक पूर्णांक नहीं है, बल्कि विधियों, विशेषताओं, पतों के साथ एक पूर्ण वस्तु है ...
nosklo

369

मैं पायथन में किसी वस्तु का आकार कैसे निर्धारित करूं?

जवाब, "बस यूज sys.getizeof" एक पूर्ण जवाब नहीं है।

यह उत्तर बिल्ट ऑब्जेक्ट्स के लिए सीधे काम करता है , लेकिन यह उन चीज़ों के लिए खाता नहीं है, जिनमें विशेष रूप से कस्टम ऑब्जेक्ट्स, ट्यूपल्स, लिस्ट्स, डीकट्स और सेट्स जैसे प्रकार शामिल हो सकते हैं। उनमें एक-दूसरे के उदाहरण, साथ ही संख्याएँ, तार और अन्य वस्तुएँ हो सकती हैं।

एक और पूरा जवाब

एनाकोंडा वितरण से 64 बिट पायथन 3.6 का उपयोग करते हुए, sys.getizeof के साथ, मैंने निम्नलिखित वस्तुओं का न्यूनतम आकार निर्धारित किया है, और ध्यान दें कि स्पेस को सेट करता है और स्पेस देता है ताकि रिक्त राशि एक निर्धारित राशि के बाद फिर से न बढ़े। भाषा के कार्यान्वयन से भिन्न):

अजगर 3:

Empty
Bytes  type        scaling notes
28     int         +4 bytes about every 30 powers of 2
37     bytes       +1 byte per additional byte
49     str         +1-4 per additional character (depending on max width)
48     tuple       +8 per additional item
64     list        +8 for each additional
224    set         5th increases to 736; 21nd, 2272; 85th, 8416; 341, 32992
240    dict        6th increases to 368; 22nd, 1184; 43rd, 2280; 86th, 4704; 171st, 9320
136    func def    does not include default args and other attrs
1056   class def   no slots 
56     class inst  has a __dict__ attr, same scaling as dict above
888    class def   with slots
16     __slots__   seems to store in mutable tuple-like structure
                   first slot grows to 48, and so on.

आप इसकी व्याख्या कैसे करते हैं? वैसे कहें कि आपके पास इसमें 10 आइटम हैं। यदि प्रत्येक आइटम 100 बाइट्स है, तो संपूर्ण डेटा संरचना कितनी बड़ी है? यह सेट 736 है क्योंकि यह एक समय 736 बाइट्स का आकार ले चुका है। फिर आप आइटम का आकार जोड़ते हैं, ताकि कुल 1736 बाइट्स हो जाएं

फ़ंक्शन और वर्ग परिभाषाओं के लिए कुछ चेतावनी:

ध्यान दें कि प्रत्येक कक्षा की परिभाषा में कक्षा के लिए एक प्रॉक्सी __dict__(48 बाइट्स) संरचना होती है। propertyकक्षा की परिभाषा में प्रत्येक स्लॉट में एक डिस्क्रिप्टर (जैसे ) होता है।

स्लॉटेड उदाहरण अपने पहले तत्व पर 48 बाइट्स के साथ शुरू होते हैं, और 8 प्रत्येक अतिरिक्त बढ़ाते हैं। केवल खाली स्लेटेड ऑब्जेक्ट्स में 16 बाइट्स होते हैं, और बिना डेटा वाले एक उदाहरण बहुत कम समझ में आता है।

इसके अलावा, प्रत्येक फ़ंक्शन परिभाषा में कोड ऑब्जेक्ट्स, शायद डोकस्ट्रिंग्स और अन्य संभावित विशेषताएं हैं, यहां तक ​​कि ए __dict__

यह भी ध्यान दें कि हम उपयोग करते हैं sys.getsizeof()क्योंकि हम सीमांत अंतरिक्ष उपयोग के बारे में परवाह करते हैं, जिसमें डस्ट से ऑब्जेक्ट के लिए कचरा संग्रह शामिल है :

getizeof () ऑब्जेक्ट की __sizeof__विधि को कॉल करता है और अतिरिक्त कचरा कलेक्टर ओवरहेड जोड़ता है यदि ऑब्जेक्ट को कचरा कलेक्टर द्वारा प्रबंधित किया जाता है।

यह भी ध्यान दें कि सूचियों का आकार बदलना (उदाहरण के लिए उन्हें दोहराते हुए) उन्हें स्पेसलोकेट करने के लिए प्रेरित करता है, इसी तरह सेट और डाइक को भी। से listobj.c स्रोत कोड :

    /* This over-allocates proportional to the list size, making room
     * for additional growth.  The over-allocation is mild, but is
     * enough to give linear-time amortized behavior over a long
     * sequence of appends() in the presence of a poorly-performing
     * system realloc().
     * The growth pattern is:  0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
     * Note: new_allocated won't overflow because the largest possible value
     *       is PY_SSIZE_T_MAX * (9 / 8) + 6 which always fits in a size_t.
     */
    new_allocated = (size_t)newsize + (newsize >> 3) + (newsize < 9 ? 3 : 6);

ऐतिहासिक आंकड़ा

पायथन 2.7 विश्लेषण, के साथ की पुष्टि की guppy.hpyऔर sys.getsizeof:

Bytes  type        empty + scaling notes
24     int         NA
28     long        NA
37     str         + 1 byte per additional character
52     unicode     + 4 bytes per additional character
56     tuple       + 8 bytes per additional item
72     list        + 32 for first, 8 for each additional
232    set         sixth item increases to 744; 22nd, 2280; 86th, 8424
280    dict        sixth item increases to 1048; 22nd, 3352; 86th, 12568 *
120    func def    does not include default args and other attrs
64     class inst  has a __dict__ attr, same scaling as dict above
16     __slots__   class with slots has no dict, seems to store in 
                   mutable tuple-like structure.
904    class def   has a proxy __dict__ structure for class attrs
104    old class   makes sense, less stuff, has real dict though.

ध्यान दें कि शब्दकोशों ( लेकिन सेट नहीं ) को पायथन 3.6 में अधिक कॉम्पैक्ट प्रतिनिधित्व मिला

मुझे लगता है कि संदर्भ के लिए अतिरिक्त आइटम प्रति 8 बाइट्स 64 बिट मशीन पर बहुत अधिक समझ में आता है। उन 8 बाइट्स स्मृति में उस जगह को इंगित करते हैं जहां निहित आइटम है। 4 बाइट्स पायथन 2 में यूनिकोड के लिए निश्चित चौड़ाई हैं, अगर मुझे सही ढंग से याद है, लेकिन पायथन 3 में, स्ट्रेट पात्रों की अधिकतम चौड़ाई के बराबर चौड़ाई का यूनिकोड बन जाता है।

(और स्लॉट्स पर अधिक जानकारी के लिए, यह उत्तर देखें )

एक अधिक पूर्ण कार्य

हम एक ऐसा फंक्शन चाहते हैं, जो लिस्ट, टुपल्स, सेट्स, डिक्ट्स obj.__dict__, और obj.__slots__अन्य चीजों के साथ-साथ उन अन्य चीजों को भी खोजे, जिनके बारे में हमने अभी तक नहीं सोचा है।

हम gc.get_referentsइस खोज को करने के लिए भरोसा करना चाहते हैं क्योंकि यह सी स्तर पर काम करता है (इसे बहुत तेज बनाता है)। नकारात्मक पक्ष यह है कि get_referents निरर्थक सदस्यों को वापस कर सकते हैं, इसलिए हमें यह सुनिश्चित करने की आवश्यकता है कि हम डबल गिनती न करें।

कक्षाएं, मॉड्यूल और फ़ंक्शंस एकल हैं - वे एक बार मेमोरी में मौजूद होते हैं। हमें उनके आकार में इतनी दिलचस्पी नहीं है, क्योंकि हम उनके बारे में बहुत कुछ नहीं कर सकते हैं - वे कार्यक्रम का एक हिस्सा हैं। यदि हम संदर्भित होने पर उन्हें गिनने से बचेंगे।

हम प्रकारों की एक ब्लैकलिस्ट का उपयोग करने जा रहे हैं ताकि हम अपने आकार की गणना में पूरे कार्यक्रम को शामिल न करें।

import sys
from types import ModuleType, FunctionType
from gc import get_referents

# Custom objects know their class.
# Function objects seem to know way too much, including modules.
# Exclude modules as well.
BLACKLIST = type, ModuleType, FunctionType


def getsize(obj):
    """sum size of object & members."""
    if isinstance(obj, BLACKLIST):
        raise TypeError('getsize() does not take argument of type: '+ str(type(obj)))
    seen_ids = set()
    size = 0
    objects = [obj]
    while objects:
        need_referents = []
        for obj in objects:
            if not isinstance(obj, BLACKLIST) and id(obj) not in seen_ids:
                seen_ids.add(id(obj))
                size += sys.getsizeof(obj)
                need_referents.append(obj)
        objects = get_referents(*need_referents)
    return size

निम्नलिखित श्वेतसूचीबद्ध फ़ंक्शन के साथ इसके विपरीत, अधिकांश ऑब्जेक्ट्स जानते हैं कि कचरा संग्रह के प्रयोजनों के लिए खुद को कैसे पार करना है (जो लगभग वही है जो हम खोज रहे हैं जब हम यह जानना चाहते हैं कि मेमोरी कुछ वस्तुओं में कितनी महंगी है। इस कार्यक्षमता का उपयोग किया जाता है। gc.get_referents।) हालांकि, यह उपाय हमारे द्वारा किए गए उद्देश्य से बहुत अधिक विस्तार में है, अगर हम सावधान नहीं हैं।

उदाहरण के लिए, फ़ंक्शन उन मॉड्यूल के बारे में बहुत कुछ जानते हैं जो वे बनाए गए हैं।

इसके विपरीत एक और बात यह है कि शब्दकोशों में कुंजी रखने वाले तार आमतौर पर इंटर्न किए जाते हैं ताकि वे डुप्लिकेट न हों। के लिए जाँच id(key)हमें डुप्लिकेट गिनती से बचने की भी अनुमति देगा, जो हम अगले भाग में करते हैं। ब्लैकलिस्ट समाधान पूरी तरह से तार हैं कि गिनती गिनती रुक जाती है।

सफेद किए गए प्रकार, पुनरावर्ती आगंतुक (पुराना कार्यान्वयन)

इनमें से अधिकांश प्रकारों को स्वयं को कवर करने के लिए, जीसी मॉड्यूल पर निर्भर होने के बजाय, मैंने इस पुनरावर्ती कार्य को सबसे पायथन वस्तुओं के आकार का अनुमान लगाने का प्रयास करने के लिए लिखा, जिसमें अधिकांश बिलियन, संग्रह मॉड्यूल में प्रकार और कस्टम प्रकार (स्लॉटेड और अन्यथा) शामिल हैं। ।

इस प्रकार का फ़ंक्शन मेमोरी के उपयोग के लिए हमारे द्वारा गिने जाने वाले प्रकारों पर बहुत अधिक बारीक नियंत्रण देता है, लेकिन इसके प्रकारों को छोड़ने का खतरा है:

import sys
from numbers import Number
from collections import Set, Mapping, deque

try: # Python 2
    zero_depth_bases = (basestring, Number, xrange, bytearray)
    iteritems = 'iteritems'
except NameError: # Python 3
    zero_depth_bases = (str, bytes, Number, range, bytearray)
    iteritems = 'items'

def getsize(obj_0):
    """Recursively iterate to sum size of object & members."""
    _seen_ids = set()
    def inner(obj):
        obj_id = id(obj)
        if obj_id in _seen_ids:
            return 0
        _seen_ids.add(obj_id)
        size = sys.getsizeof(obj)
        if isinstance(obj, zero_depth_bases):
            pass # bypass remaining control flow and return
        elif isinstance(obj, (tuple, list, Set, deque)):
            size += sum(inner(i) for i in obj)
        elif isinstance(obj, Mapping) or hasattr(obj, iteritems):
            size += sum(inner(k) + inner(v) for k, v in getattr(obj, iteritems)())
        # Check for custom object instances - may subclass above too
        if hasattr(obj, '__dict__'):
            size += inner(vars(obj))
        if hasattr(obj, '__slots__'): # can have __slots__ with __dict__
            size += sum(inner(getattr(obj, s)) for s in obj.__slots__ if hasattr(obj, s))
        return size
    return inner(obj_0)

और मैंने इसे आकस्मिक रूप से परीक्षण किया (मुझे इसे एकतरफा करना चाहिए):

>>> getsize(['a', tuple('bcd'), Foo()])
344
>>> getsize(Foo())
16
>>> getsize(tuple('bcd'))
194
>>> getsize(['a', tuple('bcd'), Foo(), {'foo': 'bar', 'baz': 'bar'}])
752
>>> getsize({'foo': 'bar', 'baz': 'bar'})
400
>>> getsize({})
280
>>> getsize({'foo':'bar'})
360
>>> getsize('foo')
40
>>> class Bar():
...     def baz():
...         pass
>>> getsize(Bar())
352
>>> getsize(Bar().__dict__)
280
>>> sys.getsizeof(Bar())
72
>>> getsize(Bar.__dict__)
872
>>> sys.getsizeof(Bar.__dict__)
280

यह कार्यान्वयन वर्ग परिभाषाओं और कार्य परिभाषाओं पर टूट जाता है क्योंकि हम उनकी सभी विशेषताओं के बाद नहीं जाते हैं, लेकिन चूंकि उन्हें प्रक्रिया के लिए केवल एक बार स्मृति में मौजूद होना चाहिए, इसलिए उनका आकार वास्तव में बहुत अधिक मायने नहीं रखता है।


5
आप यह जोड़ सकते हैं कि यह उत्तर CPython के लिए विशिष्ट है (जो आपको एनाकोंडा के माध्यम से पायथन प्राप्त कर रहा है)
gerrit

1
CPython संदर्भ कार्यान्वयन है, और मैंने अभी jython के ऑनलाइन डॉक्स की समीक्षा की है जो समान API प्रदान करता है, इसलिए मुझे विश्वास है कि यह अन्य कार्यान्वयन पर काम करेगा, इसलिए जब तक वे API को लागू नहीं करते हैं।
हारून हॉल

मेरे लिए नकाबपोश और बेपर्दा हुए खस्ता हालतों के लिए काम नहीं किया था stackoverflow.com/q/58675479/2132157
GM

95

Pympler पैकेज के asizeofमॉड्यूल ऐसा कर सकते हैं।

निम्नानुसार उपयोग करें:

from pympler import asizeof
asizeof.asizeof(my_object)

इसके विपरीत sys.getsizeof, यह आपकी स्व-निर्मित वस्तुओं के लिए काम करता है । यह भी सुन्न के साथ काम करता है।

>>> asizeof.asizeof(tuple('bcd'))
200
>>> asizeof.asizeof({'foo': 'bar', 'baz': 'bar'})
400
>>> asizeof.asizeof({})
280
>>> asizeof.asizeof({'foo':'bar'})
360
>>> asizeof.asizeof('foo')
40
>>> asizeof.asizeof(Bar())
352
>>> asizeof.asizeof(Bar().__dict__)
280
>>> A = rand(10)
>>> B = rand(10000)
>>> asizeof.asizeof(A)
176
>>> asizeof.asizeof(B)
80096

जैसा कि बताया गया है ,

(बाइट) कोड के आकार जैसे ऑब्जेक्ट्स, फ़ंक्शंस, मेथड्स, मॉड्यूल्स, आदि को सेटिंग ऑप्शन द्वारा शामिल किया जा सकता है code=True

और अगर आपको लाइव डेटा, Pympler पर अन्य दृश्य की आवश्यकता है

मॉड्यूल muppyका उपयोग पायथन एप्लिकेशन की ऑन-लाइन निगरानी के लिए किया जाता है और मॉड्यूल Class Trackerचयनित पायथन ऑब्जेक्ट्स के जीवनकाल का ऑफ-लाइन विश्लेषण प्रदान करता है।


यह कार्य बड़ी वस्तुओं के लिए काफी धीमा है। क्या एक "तेज" समकक्ष मौजूद है जो स्व-निर्मित वस्तुओं के लिए काम करता है?
शुकलस्वाग

मैंने अभी तक इसका परीक्षण नहीं किया है, लेकिन org.apache.spark.util.SizeEstimatorप्रासंगिक हो सकता है
शुकलस्वाग

1
@ शुकलस्वाग: यदि आप स्पार्क का उपयोग करते हैं, तो यह अच्छी तरह से हो सकता है। क्या आपको लगता है कि रूपांतरण + जावा अनुमान अजगर के अंतर्निहित तरीकों से तेज है? या मैंने गलत समझा?
सर्व-इन

3
ध्यान देने योग्य हो सकता है कि pymplerकार्यों और अन्य कॉलबल्स और कोड ऑब्जेक्ट्स के निष्पादन योग्य कोड आकार को ध्यान में रखने की क्षमता हो।
मृत्युंजय

मुझे एक TypeErrorअपवाद मिलता है: "कोई भी वस्तु नहीं है" कॉल करने योग्य नहीं है "जब भी मेरे कस्टम ऑब्जेक्ट के मूल्य के साथ उसके" ट्री "में कुछ सबोबैक्ट होता है None। क्या इसके लिए कोई त्वरित समाधान है?
जेम्स हिर्शोर्न

81

सुन्न सरणियों के लिए, getsizeofकाम नहीं करता है - मेरे लिए यह हमेशा किसी कारण से 40 रिटर्न देता है:

from pylab import *
from sys import getsizeof
A = rand(10)
B = rand(10000)

तब (ipython में):

In [64]: getsizeof(A)
Out[64]: 40

In [65]: getsizeof(B)
Out[65]: 40

हालांकि, खुशी:

In [66]: A.nbytes
Out[66]: 80

In [67]: B.nbytes
Out[67]: 80000

29
> सभी बिल्ट-इन ऑब्जेक्ट्स सही परिणाम लौटाएंगे, लेकिन यह तीसरे पक्ष के एक्सटेंशन के लिए सही नहीं है क्योंकि यह विशिष्ट है। docs.python.org/library/sys.html#sys.getsizeof
warvariuc

33
"यदि आप एक संख्यात्मक सरणी ( docs.scipy.org/doc/numpy/reference/arrays.ndarray.html ) का उपयोग कर रहे हैं तो आप मेमोरी में इसके आकार का मूल्यांकन करने के लिए विशेषता 'ndarray.nbytes' का उपयोग कर सकते हैं।" stackoverflow.com/a/15591157/556413
glarrain

17
मुझे लगता है कि 40 बाइट्स सही हैं, हालांकि getsizeof()केवल आपको ऑब्जेक्ट का आकार देता है (सरणी का हेडर), अंदर के डेटा का नहीं। अजगर कंटेनरों के लिए समान है sys.getsizeof([1,2,4]) == sys.getsizeof([1,123**456,4]) == 48, जबकिsys.getsizeof(123**456) = 436
yota

3
ऐसा प्रतीत होता है getsizeof()कि अपेक्षित मूल्य को वापस करने के लिए फ़ंक्शन को किसी बिंदु पर बदल दिया गया था।
dshin

15

पायथन 3.8 (Q1 2019) के कुछ परिणामों को बदल देगा sys.getsizeof, जैसा कि रेमंड हेटिंगर द्वारा यहां घोषित किया गया है:

पायथन कंटेनर 64-बिट बिल्ड पर 8 बाइट्स छोटे होते हैं।

tuple ()  48 -> 40       
list  []  64 ->56
set()    224 -> 216
dict  {} 240 -> 232

यह समस्या 33597 और इनडा नाओकी ( methane) के कॉम्पैक्ट PyGC_Head, और PR 7043 के आसपास के काम के बाद आती है

यह विचार PyGC_Head के आकार को दो शब्दों में कम कर देता है

वर्तमान में, PyGC_Head में तीन शब्द लगते हैं ; gc_prev, gc_nextऔर gc_refcnt

  • gc_refcnt परीक्षण विलोपन के लिए संग्रह करते समय उपयोग किया जाता है।
  • gc_prev ट्रैकिंग और अनट्रैकिंग के लिए उपयोग किया जाता है।

इसलिए यदि हम परीक्षण हटाए जाने के दौरान ट्रैकिंग / अनट्रैकिंग से बच सकते हैं, gc_prevऔर gc_refcntसमान मेमोरी स्पेस साझा कर सकते हैं।

देखें प्रतिबद्ध d5c875b :

Py_ssize_tसे एक सदस्य को हटा दिया PyGC_Head
सभी जीसी ट्रैक किए गए ऑब्जेक्ट (जैसे टपल, सूची, तानाशाह) का आकार 4 या 8 बाइट्स कम हो जाता है।


14

यह चीजों को गिनने के तरीके के आधार पर अधिक जटिल हो सकता है। उदाहरण के लिए, यदि आपके पास किलों की सूची है, तो क्या आप सूची के आकार को चींटियों के संदर्भों से युक्त करना चाहते हैं ? (यानी। केवल सूची, इसमें क्या निहित है) नहीं है, या क्या आप इंगित किए गए वास्तविक डेटा को शामिल करना चाहते हैं, जिस स्थिति में आपको डुप्लिकेट संदर्भों से निपटने की आवश्यकता है, और दो वस्तुओं के संदर्भ होने पर दोहरे गणना को कैसे रोकें एक ही वस्तु।

आप अजगर मेमोरी प्रोफाइलरों में से एक पर एक नज़र डालना चाह सकते हैं, जैसे कि pysizer देखने के लिए कि क्या वे आपकी आवश्यकताओं को पूरा करते हैं।


10

इस समस्या के कई बार चलने के बाद, मैंने एक छोटा सा फंक्शन (@ aaron-hall के उत्तर से प्रेरित) और परीक्षण लिखा, जो मुझे उम्मीद है कि ऐसा करने के लिए sys.getsizeof होगा:

https://github.com/bosswissam/pysize

यदि आप बैकस्टोरी में रुचि रखते हैं, तो यह यहाँ है

संपादित करें: आसान संदर्भ के लिए नीचे दिए गए कोड को संलग्न करना। सबसे अप-टू-डेट कोड देखने के लिए, कृपया गीथब लिंक देखें।

    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

7

यहाँ एक त्वरित स्क्रिप्ट है जो मैंने पिछले उत्तर के आधार पर सभी चरों के आकारों को सूचीबद्ध करने के लिए लिखी है

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

यह गलत नहीं है, यह अस्पष्ट है। sys.getizeof हमेशा रिटर्न वैल्यू की आवश्यकता होती है, इसलिए try..except के साथ ढीले प्रदर्शन की आवश्यकता नहीं है।
der_fenix

ओह, यह एक अच्छा बिंदु है और मैंने इसके बारे में नहीं सोचा था - यह जिस रूप में है, ठीक उसी तरह कोड अभी पता चलता है कि यह कालानुक्रमिक रूप से कैसे लिखा गया था - पहले मुझे सुन्न (इसलिए nbytes) के बारे में पता था, फिर मैंने एक और सामान्य समाधान देखा । स्पष्टीकरण के लिए धन्यवाद _ / \ _
अलेक्सई

7

आप उस वस्तु को प्राप्त करने के लिए धारावाहिक कर सकते हैं जो किसी वस्तु के आकार से निकटता से संबंधित हो:

import pickle

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

यदि आप ऐसी वस्तुओं को मापना चाहते हैं जिन्हें चुना नहीं जा सकता (जैसे कि लंबोदर भावों के कारण) क्लाउडपिक एक समाधान हो सकता है।


4

यदि आप लिंक किए गए (नेस्टेड) ​​ऑब्जेक्ट के आकारों को शामिल नहीं करना चाहते हैं, तो sys.getsizeof () का उपयोग करें ।

हालाँकि, अगर आप सूचियों, नेकट्स, सेट्स, ट्यूपल्स में नेस्टेड उप-ऑब्जेक्ट्स को गिनना चाहते हैं - और आमतौर पर यह वह है जो आप देख रहे हैं - नीचे दिखाए अनुसार पुनरावर्ती गहरे आकार () फ़ंक्शन का उपयोग करें:

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


3

यदि आपको ऑब्जेक्ट के सटीक आकार की आवश्यकता नहीं है, लेकिन मोटे तौर पर यह जानने के लिए कि यह कितना बड़ा है, तो एक त्वरित (और गंदा) तरीका है कि प्रोग्राम को चलने दें, समय की एक विस्तारित अवधि के लिए सोएं, और मेमोरी उपयोग की जांच करें (उदा। : इस विशेष अजगर प्रक्रिया द्वारा मैक की गतिविधि की निगरानी)। यह तब प्रभावी होगा जब आप अजगर प्रक्रिया में किसी एक बड़ी वस्तु के आकार का पता लगाने की कोशिश कर रहे हों। उदाहरण के लिए, मैं हाल ही में एक नए डेटा संरचना के मेमोरी उपयोग की जांच करना चाहता था और इसकी तुलना पायथन के सेट डेटा संरचना से करता था। पहले मैंने एक सेट में तत्वों (एक बड़े सार्वजनिक डोमेन बुक से शब्द) को लिखा, फिर प्रक्रिया के आकार की जांच की, और फिर अन्य डेटा संरचना के साथ भी ऐसा ही किया। मुझे पता चला कि एक सेट के साथ पायथन प्रक्रिया नई डेटा संरचना से दोगुनी मेमोरी ले रही है। फिर से, तुम नहीं होगा ' t प्रक्रिया द्वारा उपयोग की जाने वाली मेमोरी को वास्तव में कहने में सक्षम होना चाहिए जो ऑब्जेक्ट के आकार के बराबर है। जैसे-जैसे ऑब्जेक्ट का आकार बड़ा होता जाता है, यह करीब हो जाता है क्योंकि बाकी प्रक्रिया द्वारा खपत की गई मेमोरी उस वस्तु के आकार की तुलना में नगण्य हो जाती है जिसे आप मॉनिटर करने की कोशिश कर रहे हैं।


1
सवाल यह है कि यह अजगर में कैसे करना है , न कि केवल अजगर वस्तुओं की स्मृति का उपयोग करना , और मैक की गतिविधि मॉनिटर या किसी अन्य समान सॉफ्टवेयर का उपयोग करके प्रोग्राम को अजगर का उपयोग करना नहीं है। यह कहा जा रहा है, इस तरह से अजगर प्रक्रियाओं की स्मृति उपयोग की जाँच आम तौर पर यह सुनिश्चित करने के लिए एक अच्छा तरीका है कि कुछ भी गलत नहीं हुआ है ...
टॉम वायली

@TomWyllie, धन्यवाद, लेकिन इस जवाब को नीचा दिखाने से नकारात्मक अर्थ निकलता है कि उत्तर ही गलत है और कुछ भी पूरा नहीं करता है। मेरे द्वारा उल्लिखित विधि को पायथन में लागू नहीं किया जा सकता है, लेकिन यह पायथन ऑब्जेक्ट के आकार का मोटा अनुमान लगाने का एक आसान तरीका है। मुझे पता था कि मैं सटीक प्रश्न का उत्तर नहीं दे रहा हूं, हालांकि, विधि किसी और के लिए समान परिणाम प्राप्त करने के लिए उपयोगी हो सकती है।
पिकमेट pic

1

आप ऑब्जेक्ट के आकार को निर्धारित करने के लिए नीचे दिए गए getSizeof () का उपयोग कर सकते हैं

import sys
str1 = "one"
int_element=5
print("Memory size of '"+str1+"' = "+str(sys.getsizeof(str1))+ " bytes")
print("Memory size of '"+ str(int_element)+"' = "+str(sys.getsizeof(int_element))+ " bytes")

0

मैं इस ट्रिक का उपयोग करता हूं ... छोटी वस्तुओं पर सटीक नहीं हो सकता, लेकिन मुझे लगता है कि यह sys.getsizeof () के बजाय एक जटिल वस्तु (जैसे pygame सतह) के लिए अधिक सटीक है।

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

मेरी खिड़कियों पर 10, अजगर 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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.