পাইথনে কোনও বস্তুর আকার কীভাবে নির্ধারণ করব?


683

আমি পাইথনে স্ট্রিং, পূর্ণসংখ্যার মতো বস্তুর আকার কীভাবে পেতে পারি তা জানতে চাই।

সম্পর্কিত প্রশ্ন: পাইথন তালিকায় উপাদানটির জন্য কতগুলি বাইট রয়েছে (টিপল)?

আমি একটি এক্সএমএল ফাইল ব্যবহার করছি যার মধ্যে আকারের ক্ষেত্রগুলি রয়েছে যা মানের আকার নির্দিষ্ট করে। আমার অবশ্যই এই এক্সএমএলকে বিশদ করে আমার কোডিংটি করতে হবে do আমি যখন কোনও নির্দিষ্ট ক্ষেত্রের মান পরিবর্তন করতে চাই, আমি সেই মানটির আকার ক্ষেত্রটি যাচাই করব। এখানে আমি তুলনা করতে চাই যে আমি যে নতুন মানটি প্রবেশ করতে চাইছি এটি XML এর মতো একই আকারের কিনা। আমাকে নতুন মানের আকার পরীক্ষা করতে হবে। স্ট্রিংয়ের ক্ষেত্রে আমি এর দৈর্ঘ্য বলতে পারি। তবে ইনট, ফ্লোট ইত্যাদির ক্ষেত্রে আমি বিভ্রান্ত।

উত্তর:


665

মডিউলে সংজ্ঞায়িত sys.getsizeof ফাংশনটি কেবল ব্যবহার করুন 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
@ ছাইমজি কারণ এটি প্রতিটি বস্তু কেবলমাত্র 32 বাইট ব্যবহার করে !! বাকী অন্যান্য অবজেক্টের রেফারেন্স। আপনি যদি রেফারেন্সযুক্ত জিনিসগুলির জন্য অ্যাকাউন্ট করতে চান তবে আপনাকে __sizeof__আপনার শ্রেণীর জন্য পদ্ধতিটি নির্ধারণ করতে হবে । অন্তর্নির্মিত dictপাইথন ক্লাসটি এটি সংজ্ঞায়িত করে, এজন্য টাইপের অবজেক্ট ব্যবহার করার সময় আপনি সঠিক ফলাফলটি পান dict
নসক্লো

19
এই কার্যকারী কভারটির অস্বীকৃতি এবং ব্যতিক্রমগুলি প্রায় সমস্ত ক্ষেত্রে getsizeofকেসটিকে বাক্সের বাইরে রেখে খুব কম মূল্যের কাজ করে making
রবিনো

7
কেন পূর্ণসংখ্যা 2 24 বাইটে সঞ্চয় করা হয়?
সাহের আহওয়াল

4
@ সাহের অহওয়াল এটি কেবল একটি পূর্ণসংখ্যারই নয়, পদ্ধতি, বৈশিষ্ট্য, ঠিকানা সহ একটি সম্পূর্ণ অবজেক্ট ...
নসক্লো

369

পাইথনে কোনও বস্তুর আকার কীভাবে নির্ধারণ করব?

"Just sys.getsizeof ব্যবহার করুন" উত্তরটি সম্পূর্ণ উত্তর নয়।

এই উত্তরটি অন্তর্নির্মিত অবজেক্টগুলির জন্য সরাসরি কাজ করে , তবে কাস্টম অবজেক্টস, টিপলস, তালিকা, ডিক্টস এবং সেটগুলিতে কী কী ধরণের জিনিসগুলি নির্দিষ্টভাবে থাকতে পারে তার জন্য এটি হিসাব করে না। এগুলিতে একে অপরের উদাহরণ, পাশাপাশি সংখ্যা, স্ট্রিং এবং অন্যান্য অবজেক্ট থাকতে পারে।

আরও একটি সম্পূর্ণ উত্তর

Sys.getsizeof সহ অ্যানাকোন্ডা বিতরণ থেকে bit৪ বিট পাইথন ৩.6 ব্যবহার করে আমি নিম্নলিখিত বিষয়গুলির সর্বনিম্ন আকার নির্ধারণ করেছি এবং নোট করুন যে সেট সেট এবং ডিক্টস প্রিলোকল্ট স্পেস তাই একটি নির্দিষ্ট পরিমাণের পরে খালিগুলি আবার বৃদ্ধি না পায় (যা হতে পারে ভাষা প্রয়োগের মাধ্যমে পরিবর্তিত হয়):

পাইথন 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 বাইট হয় তবে পুরো ডেটা স্ট্রাকচারটি কতটা বড়? সেটটি নিজেই 6৩6 কারণ এটি এক সময় আকার বাড়িয়ে 73৩6 বাইট করে। তারপরে আপনি আইটেমগুলির আকার যুক্ত করুন, সুতরাং এটি মোট 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.

দ্রষ্টব্য যে অভিধানগুলি ( তবে সেট নয় ) পাইথন ৩.6-তে আরও কমপ্যাক্ট উপস্থাপনা পেয়েছে

আমি মনে করি অতিরিক্ত আইটেম প্রতি 8 বাইট রেফারেন্স একটি 64 বিট মেশিনে প্রচুর পরিমাণে বোঝায়। এই 8 বাইটগুলি স্মৃতিতে স্থানটি নির্দেশ করে অন্তর্ভুক্ত আইটেমটি রয়েছে। পাইথন 2-তে ইউনিকোডের জন্য 4 বাইটগুলি স্থির করে দেওয়া হয়েছে, যদি আমি সঠিকভাবে স্মরণ করি তবে পাইথন 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

নিম্নলিখিত শ্বেত তালিকাভুক্ত ফাংশনটির সাথে এটির বিপরীতে, বেশিরভাগ অবজেক্টগুলি জঞ্জাল সংগ্রহের উদ্দেশ্যে কীভাবে নিজেদেরকে ট্র্যাভার করতে হয় তা জেনে থাকে (যা আমরা মেমরির কতটা ব্যয়বহুল তা কতটা ব্যয়বহুল তা জানতে চাইলে আমরা প্রায় সন্ধান করি This এই কার্যকারিতাটি ব্যবহার করে gc.get_referents।) তবে, আমরা যদি যত্নবান না হই তবে এই ব্যবস্থাটি ক্ষেত্রের চেয়ে অনেক বেশি বিস্তৃত হতে চলেছে intended

উদাহরণস্বরূপ, ফাংশনগুলি সেগুলির মধ্যে তৈরি মডিউলগুলি সম্পর্কে যথেষ্ট পরিমাণে জানে।

এর বিপরীতে আরেকটি বিষয় হ'ল অভিধানে কীগুলি থাকে এমন স্ট্রিংগুলি সাধারণত ইন্টার্ন করা হয় যাতে সেগুলি নকল হয় না। অনুসন্ধান করা 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
আপনি যুক্ত করতে পারেন যে এই উত্তরটি সিপিথনের সাথে সুনির্দিষ্ট (যা আপনি অ্যানাকোন্ডার মাধ্যমে পাইথন পাওয়ার দ্বারা বোঝানো হয়েছে)
জেরিট

1
সিপিথন হ'ল রেফারেন্স বাস্তবায়ন, এবং আমি ঠিক জেথনের অনলাইন ডক্সগুলি পর্যালোচনা করেছি যা একই এপিআই সরবরাহ করে, তাই আমি বিশ্বাস করি যে এপিআইগুলি বাস্তবায়ন করার পরে এটি অন্যান্য বাস্তবায়নের ক্ষেত্রে কাজ করবে।
অ্যারন হল

আমার জন্য কাজ না করে ছদ্মবেশী এবং মুখোশহীন numpy অ্যারে stackoverflow.com/q/58675479/2132157
জিএম

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

এবং আপনার যদি লাইভ ডেটা, পিম্পলারের অন্যান্য ভিউর প্রয়োজন হয়

মডিউলটি muppyপাইথন অ্যাপ্লিকেশনটির অন-লাইন পর্যবেক্ষণের জন্য ব্যবহৃত হয় এবং মডিউল Class Trackerনির্বাচিত পাইথন বস্তুর আজীবন অফ-লাইন বিশ্লেষণ সরবরাহ করে।


বৃহত বস্তুর জন্য এই ফাংশনটি বেশ ধীর। স্ব-নির্মিত বস্তুর জন্য কাজ করে এমন একটি "দ্রুত" সমতুল্য কি বিদ্যমান?
শুক্লসওয়াগ

আমি এটি এখনও পরীক্ষা করি নি, তবে org.apache.spark.util.SizeEstimatorপ্রাসঙ্গিক হতে পারে
শুক্লসওয়াগ

1
@ শুক্লসওয়াগ: আপনি যদি স্ফুলিঙ্গ ব্যবহার করেন তবে তা ভালই হতে পারে। আপনি কি মনে করেন যে রূপান্তর + জাভা অনুমানটি পাইথনের অন্তর্নির্মিত পদ্ধতিগুলির চেয়ে দ্রুত? নাকি আমি ভুল বুঝেছি?
সার্ভ-ইন

3
pymplerফাংশনগুলির এক্সিকিউটেবল কোড আকার এবং অন্যান্য কলযোগ্য এবং কোড অবজেক্টগুলিকে অ্যাকাউন্টে নেওয়ার ক্ষমতা রয়েছে তা লক্ষ করার মতো।
mtraceur

আমি একটি TypeErrorব্যতিক্রম পেয়েছি : "'ননটাইপ' অবজেক্টটি কল করা যায় না" যখনই আমার কাস্টম অবজেক্টটির মান সহ "ট্রি" তে কিছু সাববজেক্ট থাকে None। এই জন্য কোন দ্রুত workaround আছে?
জেমস হিরশর্ন

81

ন্যালি অ্যারেগুলির জন্য, getsizeofকাজ করে না - আমার জন্য এটি সর্বদা কোনও কারণে 40 ফেরত দেয়:

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

তারপরে (আইপথনে):

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
> সমস্ত অন্তর্নির্মিত অবজেক্টগুলি সঠিক ফলাফলগুলি ফিরিয়ে দেবে, তবে এটি বাস্তবায়নের নির্দিষ্টকরণের কারণে তৃতীয় পক্ষের এক্সটেনশনের ক্ষেত্রে এটি সত্য রাখতে হবে না true docs.python.org/library/sys.html#sys.getsizeof
ওয়ারওয়ারিয়াক

33
"যদি আপনি একটি নম্পী অ্যারে ব্যবহার করেন ( ডকস.সিকিপি.আর.ডোক / নম্পি / রেফারেন্স / অ্যারাই.আররেইএইচটিএমএল ) তবে আপনি মেমরির আকারটি মূল্যায়ন করতে '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
যোটা

3
getsizeof()প্রত্যাশিত মানটি ফিরিয়ে দেওয়ার জন্য এটি ফাংশনটি কোনও এক সময় পরিবর্তিত হয়েছিল বলে মনে হয়।
shshin

15

পাইথন 3.8 (Q1 2019) এর ফলাফলের কিছু পরিবর্তন করবে sys.getsizeof, এখানে রেইমন্ড হেটিংগার ঘোষণা করেছেন:

পাইথন পাত্রে by৪-বিট বিল্ডসে 8 বাইট ছোট।

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

এটি 33597 ইস্যু এবং ইনাডা নওকি ( methane) এর কমপ্যাক্ট পাইজিসিহাইড এবং এর পিআর 7043 এর কাজের পরে আসে

এই ধারণাটি পাইগিসিহাইড আকার দুটি শব্দে হ্রাস করে

বর্তমানে পাইজিসিহাইড তিনটি শব্দ নেয় ; gc_prev, gc_nextএবং gc_refcnt

  • gc_refcnt সংগ্রহ করার সময়, পরীক্ষার মোছার জন্য ব্যবহৃত হয়।
  • gc_prev ট্র্যাকিং এবং ট্রেড করার জন্য ব্যবহৃত হয়।

সুতরাং আমরা ট্র্যাকিং / untracking যখন বিচারের মুছে ফেলার এড়াতে পারেন, যদি gc_prevএবং gc_refcntএকই মেমরি স্পেস শেয়ার করতে পারেন।

কমিট ডি 5c875 বি দেখুন :

Py_ssize_tথেকে একজন সদস্যকে সরানো হয়েছে PyGC_Head
সমস্ত জিসি ট্র্যাক করা অবজেক্টস (যেমন: টিপল, তালিকা, ডিক) আকার 4 বা 8 বাইট হ্রাস করা হয়েছে।


14

আপনি কীভাবে জিনিস গণনা করতে চান তার উপর নির্ভর করে এটি আরও জটিল হতে পারে। উদাহরণস্বরূপ, আপনার যদি কালিগুলির একটি তালিকা থাকে তবে আপনি কি সূত্রগুলির উল্লেখ সহ তালিকার আকার চান ? (উদাহরণস্বরূপ, কেবলমাত্র এটি অন্তর্ভুক্ত রয়েছে তার তালিকা নয়), অথবা আপনি যে নকল রেফারেন্সের সাথে ডিলিট করতে হবে এবং যেভাবে দুটি বস্তুতে রেফারেন্স রয়েছে তখন কীভাবে দ্বিগুণ গণনা রোধ করতে হবে সেই ক্ষেত্রে যে প্রকৃত ডেটা রয়েছে তাতে আপনি কী অন্তর্ভুক্ত করতে চান? একই জিনিস।

পাইথন মেমোরি প্রোফাইলগুলির মধ্যে একটির দিকে নজর রাখতে পারেন , যেমন পাইসাইজার তারা আপনার চাহিদা পূরণ করে কিনা তা দেখার জন্য।


10

এই সমস্যাটি নিজেই বহুবার চালানোর পরে, আমি একটি ছোট ফাংশন লিখেছিলাম (@ অ্যারন-হলের উত্তর দ্বারা অনুপ্রাণিত) এবং পরীক্ষাগুলি যা আমার সিএস.জেটসাইফের কাছ থেকে প্রত্যাশা করত তা করে:

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.getsizeof সর্বদা মানটি প্রয়োজন ফেরত দেবে, তাই চেষ্টা করুন..অযুক্তি দিয়ে পারফরম্যান্স শিথিল করার দরকার নেই।
der_fenix

ওহ, এটি একটি ভাল পয়েন্ট এবং আমি এটি সম্পর্কে ভাবিনি - এটি এখনকার আকারে কোডটি দেখায় যে এটি কীভাবে কালানুক্রমিকভাবে লিখিত হয়েছিল - প্রথমে আমি নাম্পার সম্পর্কে জানতাম (অতএব এনবিটস), তারপরে আমি আরও জেনেরিক সমাধানটি সন্ধান করেছি । _ / \ _
আলেক্সি

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

যদি আপনাকে অবজেক্টের সঠিক আকারের প্রয়োজন না হয় তবে মোটামুটি এটি কতটা বড় তা জানতে, একটি দ্রুত (এবং নোংরা) উপায় হ'ল প্রোগ্রামটি চালিত হওয়া, দীর্ঘ সময়ের জন্য ঘুমানো এবং মেমরির ব্যবহার পরীক্ষা করা (প্রাক্তন : ম্যাকের ক্রিয়াকলাপের নিরীক্ষক) এই অজগর প্রক্রিয়াটি দ্বারা। এটি কার্যকর হবে যখন আপনি অজগর প্রক্রিয়াতে একটি একক বৃহত অবজেক্টের আকার অনুসন্ধান করার চেষ্টা করছেন। উদাহরণস্বরূপ, আমি সম্প্রতি একটি নতুন ডেটা স্ট্রাকচারের মেমরির ব্যবহারটি পরীক্ষা করতে এবং পাইথনের সেট ডেটা কাঠামোর সাথে তুলনা করতে চেয়েছিলাম। প্রথমে আমি একটি সেটগুলিতে উপাদানগুলি (একটি বৃহত পাবলিক ডোমেন বইয়ের শব্দগুলি) লিখেছিলাম, তারপরে প্রক্রিয়াটির আকারটি পরীক্ষা করেছিলাম এবং তারপরে অন্যান্য ডেটা কাঠামোর সাথে একই জিনিসটি করেছি। আমি খুঁজে পেয়েছি পাইথন প্রক্রিয়াটি একটি সেট সহ নতুন ডেটা স্ট্রাকচারের দ্বিগুণ মেমরি নিচ্ছে। আবার তুমি চাইবে প্রক্রিয়া দ্বারা ব্যবহৃত মেমরিটি অবজেক্টের আকারের সমান বলে ঠিক বলতে সক্ষম হবেনা। অবজেক্টটির আকার বড় হওয়ার সাথে সাথে, প্রক্রিয়াটির বাকী অংশগুলির দ্বারা গ্রাহিত স্মৃতিটি আপনি যে বস্তুর নিরীক্ষণের চেষ্টা করছেন তার আকারের তুলনায় নগন্য হয়ে ওঠে।


1
প্রশ্ন হল কিভাবে এটা করতে অনুরোধ জানাবে পাইথন মধ্যে শুধু নয় মেমোরি ব্যবহার খোঁজার এর পাইথন বস্তু, এবং একটি ম্যাক এর কার্যকলাপ মনিটর বা অনুরূপ কোন সফ্টওয়্যার ব্যবহার প্রোগ্রামেটিক্যালি পাইথন ব্যবহার করছে না। বলা হচ্ছে, অজগর প্রক্রিয়াগুলির মেমরির ব্যবহার এইভাবে পরীক্ষা করা সাধারণত কোনও ভুল হয়েছে না তা নিশ্চিত করার একটি ভাল উপায় ...
টম উইলি

@ টমওয়্যালি, ধন্যবাদ, তবে এই উত্তরটিকে নিম্নচাপ দেওয়া নেতিবাচক ধারণাটি বহন করে যে উত্তরটি নিজেই ভুল এবং কোনও কিছুই পূরণ করে না। আমি যে পদ্ধতিটি উল্লেখ করেছি তা পাইথনে প্রয়োগ করা যেতে পারে না তবে এটি পাইথন বস্তুর আকারের মোটামুটি অনুমান করার এক সহজ উপায়। আমি জানতাম যে আমি সঠিক প্রশ্নের উত্তর দিচ্ছি না, তবে এই পদ্ধতিটি অন্য কারও জন্য অনুরূপ ফলাফল পেতে কার্যকর হতে পারে।
পিকমেট

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

আমি এই কৌশলটি ব্যবহার করি ... ছোট বস্তুর উপর মে সঠিক হতে পারে না তবে আমি মনে করি এটি জটিল বস্তুর (পাইগাম পৃষ্ঠের মতো) সিএস.জেটসাইফের () এর চেয়ে বেশি সঠিক much

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
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.