ফাইল আকারের মানব পাঠযোগ্য সংস্করণ পেতে পুনরায় ব্যবহারযোগ্য লাইব্রেরি?


238

ওয়েবে বিভিন্ন স্নিপেট রয়েছে যা আপনাকে বাইট আকার থেকে মানব পাঠযোগ্য আকার ফেরত দেওয়ার জন্য একটি ফাংশন দেয়:

>>> human_readable(2048)
'2 kilobytes'
>>>

তবে এখানে কি পাইথন লাইব্রেরি রয়েছে?


2
আমি মনে করি এটি "একটি লাইব্রেরির প্রয়োজন খুব ছোট একটি কাজ" শিরোনামের আওতায় পড়ে। আপনি যদি তাড়াতাড়ি.ফাইলসাইজ করার উত্সটি দেখেন তবে কয়েক ডজন লাইন কোড সহ কেবলমাত্র একটি ফাংশন রয়েছে। এমনকি এটি কমপ্যাক্ট করা যেতে পারে।
বেন ফাঁকা

8
লাইব্রেরি ব্যবহারের সুবিধাটি হ'ল এটি সাধারণত পরীক্ষা করা হয় (এর সম্পাদনাতে কোনও বাগ প্রবর্তিত হলে এমন পরীক্ষা করা যেতে পারে)। আপনি যদি পরীক্ষাগুলি যোগ করেন তবে এটি আর 'কোডের ডজন লাইন' নয় :-)
শ্রীধর রত্নাকুমার

পাইথন সম্প্রদায়ের চাকাটি পুনরায় উদ্ভাবনের পরিমাণটি পাগল এবং হাস্যকর। শুধু ls -h /path/to/file.ext কাজটি করবে। এটি বলার পরে, গৃহীত উত্তরটি একটি ভাল কাজ করছে। পারিতোষিক।
এডওয়ার্ড অং

উত্তর:


522

উপরের "খুব সহজে একটি লাইব্রেরির প্রয়োজন টাস্ক" বিষয়টিকে সরল বাস্তবায়নের মাধ্যমে সম্বোধন করা:

def sizeof_fmt(num, suffix='B'):
    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)

সমর্থন করে:

  • সমস্ত বর্তমানে বাইনারি উপসর্গ পরিচিত
  • নেতিবাচক এবং ধনাত্মক সংখ্যা
  • সংখ্যা 1000 ইওবাইবাইটের চেয়ে বড়
  • স্বেচ্ছাসেবী ইউনিট (সম্ভবত আপনি গিবিবিটস গণনা করতে চান!)

উদাহরণ:

>>> sizeof_fmt(168963795964)
'157.4GiB'

ফ্রেড Cirera দ্বারা


4
সংখ্যা এবং ইউনিটের মধ্যে একটি স্থান থাকা উচিত। আপনি যদি এইচটিএমএল বা ল্যাটেক্স আউটপুট করে থাকেন তবে এটি একটি নন-ব্রেকিং-স্পেস হওয়া উচিত।
জোছ

3
কেবল একটি চিন্তাভাবনা, তবে অন্য (?) প্রত্যয় ব্যতীত B(অর্থাত্ বাইট ব্যতীত অন্য ইউনিটগুলির জন্য) আপনি কি চান যে ফ্যাক্টরটি 1000.0সংখ্যাটির চেয়ে বেশি হওয়া উচিত 1024.0?
এ্যানেন্ট্রপিক

5
আপনি যদি দশমিক উপাদানটির যথাযথতা বাড়াতে চান তবে 14 এবং 6 এর লাইনে আপনি যে কোনও নির্ভুলতা চান তা পরিবর্তন করুন ।
ম্যাথু জি

44
এই "খুব ছোট একটি টাস্ক" -র এই সমস্ত পুনরাবৃত্তি পরীক্ষাগুলি সহ একটি লাইব্রেরিতে আবদ্ধ করে রাখা হয় তবে অবশ্যই দুর্দান্ত।
fess।

6
@ MD004 এটি অন্যভাবে। উপসর্গগুলি 1 কেবি = 1000 বি এবং 1 কিবি = 1024 বি হিসাবে সংজ্ঞায়িত করা হয়েছে
আগুয়ার

116

একটি লাইব্রেরিতে এমন সমস্ত কার্যকারিতা রয়েছে যা দেখে মনে হয় আপনি খুঁজছেন humanizehumanize.naturalsize()আপনি যা খুঁজছেন তা সবই করা মনে হচ্ছে।


9
কিছু উদাহরণ ওপি থেকে তথ্য ব্যবহার করছে: humanize.naturalsize(2048) # => '2.0 kB' ,humanize.naturalsize(2048, binary=True) # => '2.0 KiB' humanize.naturalsize(2048, gnu=True) # => '2.0K'
RubenLaguna

32

এখানে আমার সংস্করণ। এটি কোনও ফোর-লুপ ব্যবহার করে না। এটি অবিচ্ছিন্ন জটিলতা রয়েছে, হে ( 1 ), এবং তাত্ত্বিকভাবে এখানে উত্তরগুলির চেয়ে বেশি দক্ষ যা একটি লুপ ব্যবহার করে।

from math import log
unit_list = zip(['bytes', 'kB', 'MB', 'GB', 'TB', 'PB'], [0, 0, 1, 2, 2, 2])
def sizeof_fmt(num):
    """Human friendly file size"""
    if num > 1:
        exponent = min(int(log(num, 1024)), len(unit_list) - 1)
        quotient = float(num) / 1024**exponent
        unit, num_decimals = unit_list[exponent]
        format_string = '{:.%sf} {}' % (num_decimals)
        return format_string.format(quotient, unit)
    if num == 0:
        return '0 bytes'
    if num == 1:
        return '1 byte'

কী চলছে তা আরও পরিষ্কার করার জন্য, আমরা স্ট্রিং ফর্ম্যাটিংয়ের কোডটি বাদ দিতে পারি। এখানে লাইনগুলি আসলে কাজটি করে:

exponent = int(log(num, 1024))
quotient = num / 1024**exponent
unit_list[exponent]

2
আপনি যখন এই জাতীয় একটি সংক্ষিপ্ত কোডটি অপ্টিমাইজ করার কথা বলছেন তবে কেন / এলিফ / অন্যটি ব্যবহার করবেন না? আপনার সর্বশেষ চেক নাম্বার == 1 অপ্রয়োজনীয় যদি না আপনি negativeণাত্মক ফাইলের আকার আশা করেন। অন্যথায়: দুর্দান্ত কাজ, আমি এই সংস্করণটি পছন্দ করি।
টেড

2
আমার কোড অবশ্যই আরও অনুকূলিত হতে পারে। যাইহোক, আমার বক্তব্যটি দেখানো ছিল যে এই কাজটি ধ্রুবক জটিলতায় সমাধান করা যেতে পারে।
জোকি

37
লুপগুলির জন্য উত্তরগুলি ও (1), কারণ লুপগুলির জন্য সীমাবদ্ধ - তাদের গণনার সময় ইনপুটটির আকারের সাথে স্কেল করে না (আমাদের সীমাহীন এসআই উপসর্গগুলি নেই)।
থমাস মাইনর

1
সম্ভবত ফর্ম্যাটিংয়ের জন্য কমা যুক্ত করা উচিত, তাই প্রদর্শিত 1000হবে 1,000 bytes
আইটিব

3
দ্রষ্টব্য যে পাইথন 3 ব্যবহার করার সময়, জিপ একটি পুনরাবৃত্তিকে রিটার্ন দেয়, সুতরাং আপনাকে এটি তালিকা () দিয়ে মোড়ানো দরকার। unit_list = list(zip(['bytes', 'kB', 'MB', 'GB', 'TB', 'PB'], [0, 0, 1, 2, 2, 2]))
ডোনারব

30

পাইথন 3..6+ এ নিম্নলিখিত কাজগুলি হল, আমার মতে উত্তরটি এখানে বোঝা সহজ, এবং আপনাকে ব্যবহৃত দশমিক জায়গাগুলির পরিমাণ কাস্টমাইজ করতে দেয়।

def human_readable_size(size, decimal_places=3):
    for unit in ['B','KiB','MiB','GiB','TiB']:
        if size < 1024.0:
            break
        size /= 1024.0
    return f"{size:.{decimal_places}f}{unit}"

26

যদিও আমি জানি যে এই প্রশ্নটি প্রাচীন, আমি সম্প্রতি এমন একটি সংস্করণ নিয়ে এসেছি যা লুপগুলি এড়িয়ে চলে, log2যেটি আকারের আদেশটি শিফট হিসাবে দ্বিগুণ হয় এবং প্রত্যয় তালিকায় একটি সূচক হিসাবে নির্ধারণ করে:

from math import log2

_suffixes = ['bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']

def file_size(size):
    # determine binary order in steps of size 10 
    # (coerce to int, // still returns a float)
    order = int(log2(size) / 10) if size else 0
    # format file size
    # (.4g results in rounded numbers for exact matches and max 3 decimals, 
    # should never resort to exponent values)
    return '{:.4g} {}'.format(size / (1 << (order * 10)), _suffixes[order])

এর পাঠযোগ্যতার জন্য অযৌক্তিক হিসাবে ভাল বিবেচনা করা যেতে পারে, যদিও :)


1
আমি লগ 2 জিনিসটি পছন্দ করার সময় আপনার আকারটি হ্যান্ডেল করা উচিত == 0!
মার্টি নিতো

হয় আপনি মোড়ানো প্রয়োজন sizeবা (1 << (order * 10)মধ্যে float()গত লাইন (পাইথন 2 জন্য) হবে।
হার্ভে

এফওয়াইআই: কারও কারও import mathএখানে প্রয়োজন হতে পারে ।
মনস্টো

@ মমস্তো সত্য, যুক্ত :)
এফআইডিআইওটি

এই কতটা কমপ্যাক্ট প্রেম! ভাগ করার জন্য আপনাকে ধন্যবাদ।
জন ক্র্যাফোর্ড

17

সবসময় তাদের মধ্যে একজন হতে হবে। আচ্ছা আজ এটা আমি। এখানে একটি ওয়ান-লাইনারের সমাধান - বা দুটি লাইন যদি আপনি ফাংশনের স্বাক্ষরটি গণনা করেন।

def human_size(bytes, units=[' bytes','KB','MB','GB','TB', 'PB', 'EB']):
    """ Returns a human readable string reprentation of bytes"""
    return str(bytes) + units[0] if bytes < 1024 else human_size(bytes>>10, units[1:])

>>> human_size(123)
123 bytes
>>> human_size(123456789)
117GB

1
এফওয়াইআই, আউটপুটটি সর্বদা গোল হয়ে যাবে।
wp-overwatch.com

1
ডিফল্ট যুক্তি হিসাবে কোনও তালিকার ব্যবহার এড়াতে পদ্ধতির অভ্যন্তরের ইউনিটগুলির জন্য ডিফল্ট তালিকাটি অর্পণ করা ভাল না? (এবং units=Noneপরিবর্তে ব্যবহার করে)
Imanol

3
@ আইমানলইজাগুইয়ের সেরা অনুশীলনগুলি বলবে যে আপনি পরামর্শ হিসাবে এটি করা ভাল ধারণা, সুতরাং আপনি অজান্তেই কোনও প্রোগ্রামে বাগগুলি প্রবর্তন করবেন না। তবে, লিখিত হিসাবে এই ফাংশনটি নিরাপদ কারণ ইউনিটগুলির তালিকা কখনই হেরফের হয় না। যদি এটি ম্যানিপুলেটেড হয়, পরিবর্তনগুলি স্থায়ী হবে এবং পরবর্তী কোনও ফাংশন কলগুলি ইউনিট আর্গুমেন্টের জন্য ডিফল্ট আর্গুমেন্ট হিসাবে তালিকার একটি ম্যানিপুলেটেড সংস্করণ গ্রহণ করবে।
wp-overwatch.com

পাইথন 3 এর জন্য, যদি আপনি দশমিক বিন্দু চান, তবে পরিবর্তে এটি ব্যবহার করুন: human `` Def হিউম্যান_সাইজ (fsize, ইউনিট = ['বাইটস', 'কেবি', 'এমবি', 'জিবি', 'টিবি', 'পিবি', 'EB']): "{: .2f} {}" ফর্ম্যাট (ফ্লোট (fsize), ইউনিট [0]) ফিজাইজ হলে <1024 অন্য হিউম্যান_সাইজ (fsize / 1024, ইউনিট [1:]) `` `
ওমর

15

আপনি যদি জ্যাঙ্গো ইনস্টলড ব্যবহার করছেন তবে আপনি ফাইলসাইফর্ম্যাটও চেষ্টা করতে পারেন :

from django.template.defaultfilters import filesizeformat
filesizeformat(1073741824)

=>

"1.0 GB"

1
আমার জন্য এই এক downside হয় যে এটা গিগাবাইট ব্যবহার GiB পরিবর্তে যদিও এটি দ্বারা 1024. বিভাজক হচ্ছে
Pepedou

9

এই জাতীয় একটি গ্রন্থাগার হুইল.ফাইলসাইজ

>>> from hurry.filesize import alternative
>>> size(1, system=alternative)
'1 byte'
>>> size(10, system=alternative)
'10 bytes'
>>> size(1024, system=alternative)
'1 KB'

3
তবে এই গ্রন্থাগারটি খুব স্বনির্ধারিত নয়। >>> তাড়াতাড়ি থেকে import 2M '।
শ্রীধর রত্নকুমার

এছাড়াও মনে রাখবেন যে হুট করেই কোডটি দখল করা খুব সহজ। ফাইলেসাইজ করে এটিকে সরাসরি আপনার নিজের কোডে রেখে দেওয়া, যদি আপনি নির্ভরতা সিস্টেম এবং এর মতো কাজ করে থাকেন। লোকেরা এখানে যে স্নিপেটগুলি সরবরাহ করছে এটি এটি প্রায় সংক্ষিপ্ত।
mlissner

@ শ্রীদাররত্নকুমার, অতি-অনুমানের সমস্যাটি কিছুটা বুদ্ধিমানের সাথে মোকাবেলার জন্য দয়া করে আমার গাণিতিক হ্যাক দেখুন । পদ্ধতির আরও উন্নতি করা যেতে পারে?
একিউম্যানাস

9

1000 বা কিবিবাইটের শক্তি ব্যবহার করা আরও প্রমিত-বান্ধব হবে:

def sizeof_fmt(num, use_kibibyte=True):
    base, suffix = [(1000.,'B'),(1024.,'iB')][use_kibibyte]
    for x in ['B'] + map(lambda x: x+suffix, list('kMGTP')):
        if -base < num < base:
            return "%3.1f %s" % (num, x)
        num /= base
    return "%3.1f %s" % (num, x)

পিএস কখনও এমন লাইব্রেরিতে বিশ্বাস করবেন না যা হাজার হাজার কে (বড় হাতের) প্রত্যয় দিয়ে মুদ্রণ করে :)


P.S. Never trust a library that prints thousands with the K (uppercase) suffix :)কেন না? কোডটি নিখুঁতভাবে সাবলীল হতে পারে এবং লেখক কিলো কেসিংয়ের বিষয়টি বিবেচনা করেননি। আপনার নিয়মের উপর ভিত্তি করে যে কোনও কোড স্বয়ংক্রিয়ভাবে বরখাস্ত করা বেশ সুন্দর বলে মনে হচ্ছে ...
ডগলাস গ্যাসকেল

7

এটি প্রায় কোনও পরিস্থিতিতে আপনার যা প্রয়োজন প্রয়োজন তা করবে, alচ্ছিক যুক্তিগুলির সাথে স্বনির্ধারিত, এবং আপনি দেখতে পাচ্ছেন, বেশ স্ব-ডকুমেন্টিং:

from math import log
def pretty_size(n,pow=0,b=1024,u='B',pre=['']+[p+'i'for p in'KMGTPEZY']):
    pow,n=min(int(log(max(n*b**pow,1),b)),len(pre)-1),n*b**pow
    return "%%.%if %%s%%s"%abs(pow%(-pow-1))%(n/b**float(pow),pre[pow],u)

উদাহরণ আউটপুট:

>>> pretty_size(42)
'42 B'

>>> pretty_size(2015)
'2.0 KiB'

>>> pretty_size(987654321)
'941.9 MiB'

>>> pretty_size(9876543210)
'9.2 GiB'

>>> pretty_size(0.5,pow=1)
'512 B'

>>> pretty_size(0)
'0 B'

উন্নত কাস্টমাইজেশন:

>>> pretty_size(987654321,b=1000,u='bytes',pre=['','kilo','mega','giga'])
'987.7 megabytes'

>>> pretty_size(9876543210,b=1000,u='bytes',pre=['','kilo','mega','giga'])
'9.9 gigabytes'

এই কোডটি পাইথন 2 এবং পাইথন 3 উভয়ই সামঞ্জস্যপূর্ণ। পিইপি 8 কমপ্লায়েন্স পাঠকের জন্য অনুশীলন। মনে রাখবেন, এটি আউটপুটটি বেশ সুন্দর।

হালনাগাদ:

যদি আপনার হাজার হাজার কমা প্রয়োজন হয় তবে কেবল সুস্পষ্ট এক্সটেনশনটি প্রয়োগ করুন:

def prettier_size(n,pow=0,b=1024,u='B',pre=['']+[p+'i'for p in'KMGTPEZY']):
    r,f=min(int(log(max(n*b**pow,1),b)),len(pre)-1),'{:,.%if} %s%s'
    return (f%(abs(r%(-r-1)),pre[r],u)).format(n*b**pow/b**float(r))

উদাহরণ স্বরূপ:

>>> pretty_units(987654321098765432109876543210)
'816,968.5 YiB'


6

তাড়াতাড়ি.ফাইলসাইজ () এর বিকল্প হিসাবে সরবরাহ করা স্নিপেটে রিফিং, এখানে একটি স্নিপেট রয়েছে যা ব্যবহৃত উপসর্গের উপর ভিত্তি করে বিবিধ নির্ভুলতা সংখ্যা দেয়। এটি কিছু স্নিপেটের মতো নিখরচায় নয়, তবে ফলাফলগুলি পছন্দ করি।

def human_size(size_bytes):
    """
    format a size in bytes into a 'human' file size, e.g. bytes, KB, MB, GB, TB, PB
    Note that bytes/KB will be reported in whole numbers but MB and above will have greater precision
    e.g. 1 byte, 43 bytes, 443 KB, 4.3 MB, 4.43 GB, etc
    """
    if size_bytes == 1:
        # because I really hate unnecessary plurals
        return "1 byte"

    suffixes_table = [('bytes',0),('KB',0),('MB',1),('GB',2),('TB',2), ('PB',2)]

    num = float(size_bytes)
    for suffix, precision in suffixes_table:
        if num < 1024.0:
            break
        num /= 1024.0

    if precision == 0:
        formatted_size = "%d" % num
    else:
        formatted_size = str(round(num, ndigits=precision))

    return "%s %s" % (formatted_size, suffix)


4

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

class Filesize(object):
    """
    Container for a size in bytes with a human readable representation
    Use it like this::

        >>> size = Filesize(123123123)
        >>> print size
        '117.4 MB'
    """

    chunk = 1024
    units = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB']
    precisions = [0, 0, 1, 2, 2, 2]

    def __init__(self, size):
        self.size = size

    def __int__(self):
        return self.size

    def __str__(self):
        if self.size == 0: return '0 bytes'
        from math import log
        unit = self.units[min(int(log(self.size, self.chunk)), len(self.units) - 1)]
        return self.format(unit)

    def format(self, unit):
        if unit not in self.units: raise Exception("Not a valid file size unit: %s" % unit)
        if self.size == 1 and unit == 'bytes': return '1 byte'
        exponent = self.units.index(unit)
        quotient = float(self.size) / self.chunk**exponent
        precision = self.precisions[exponent]
        format_string = '{:.%sf} {}' % (precision)
        return format_string.format(quotient, unit)

3

আমি প্রেরকের দশমিক সংস্করণের স্থির যথাযথতা পছন্দ করি , সুতরাং উপরের জক্তির উত্তরের সাথে এর এক ধরণের সংকর সংকেত দেওয়া আছে (আপনি কি জানেন যে আপনি অ-পূর্ণসংখ্যার বেসগুলির সাথে লগ নিতে পারেন?):

from math import log
def human_readable_bytes(x):
    # hybrid of https://stackoverflow.com/a/10171475/2595465
    #      with https://stackoverflow.com/a/5414105/2595465
    if x == 0: return '0'
    magnitude = int(log(abs(x),10.24))
    if magnitude > 16:
        format_str = '%iP'
        denominator_mag = 15
    else:
        float_fmt = '%2.1f' if magnitude % 3 == 1 else '%1.2f'
        illion = (magnitude + 1) // 3
        format_str = float_fmt + ['', 'K', 'M', 'G', 'T', 'P'][illion]
    return (format_str % (x * 1.0 / (1024 ** illion))).lstrip('0')


2

আধুনিক জাঙ্গোতে স্ব-টেম্পলেট ট্যাগ রয়েছে filesizeformat:

human-readableফাইলের আকারের মতো মান (যেমন '13 কেবি ',' 4.1 এমবি ',' 102 বাইট 'ইত্যাদি) ফর্ম্যাট করে ।

উদাহরণ স্বরূপ:

{{ value|filesizeformat }}

মান 123456789 হয়, আউটপুট 117.7 মেগাবাইট হবে।

আরও তথ্য: https://docs.djangoproject.com/en/1.10/ref/templates/builtins/#filesizeformat


2

সাধারণ 2 লাইনার সম্পর্কে কীভাবে:

def humanizeFileSize(filesize):
    p = int(math.floor(math.log(filesize, 2)/10))
    return "%.3f%s" % (filesize/math.pow(1024,p), ['B','KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB'][p])

এটি হুডের নীচে কীভাবে কাজ করে তা এখানে:

  1. লগ 2 গণনা (ফাইলাইজ)
  2. নিকটতম ইউনিট পেতে এটি 10 ​​দ্বারা ভাগ করে। (উদাহরণস্বরূপ, যদি আকারটি 5000 বাইট হয় তবে নিকটতম ইউনিট Kb, সুতরাং উত্তরটি X কিবি হওয়া উচিত)
  3. file_size/value_of_closest_unitইউনিট সহ ফিরে আসে ।

ফাইলাইজ 0 বা negativeণাত্মক হলে তবে এটি কাজ করে না (কারণ লগ 0 এবং -তে সংখ্যার জন্য সংজ্ঞায়িত)। আপনি তাদের জন্য অতিরিক্ত চেক যোগ করতে পারেন:

def humanizeFileSize(filesize):
    filesize = abs(filesize)
    if (filesize==0):
        return "0 Bytes"
    p = int(math.floor(math.log(filesize, 2)/10))
    return "%0.2f %s" % (filesize/math.pow(1024,p), ['Bytes','KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB'][p])

উদাহরণ:

>>> humanizeFileSize(538244835492574234)
'478.06 PiB'
>>> humanizeFileSize(-924372537)
'881.55 MiB'
>>> humanizeFileSize(0)
'0 Bytes'

দ্রষ্টব্য - কেবি এবং কিবি-র মধ্যে পার্থক্য রয়েছে। কেবি এর অর্থ 1000 বাইট, যেখানে কিবি এর অর্থ 1024 বাইট। কেবি, এমবি, জিবি সবই 1000 এর গুণক, যেখানে কিবি, এমআইবি, জিআইবি ইত্যাদি সমস্ত 1024 এর গুণক it এটি সম্পর্কে আরও এখানে


1
def human_readable_data_quantity(quantity, multiple=1024):
    if quantity == 0:
        quantity = +0
    SUFFIXES = ["B"] + [i + {1000: "B", 1024: "iB"}[multiple] for i in "KMGTPEZY"]
    for suffix in SUFFIXES:
        if quantity < multiple or suffix == SUFFIXES[-1]:
            if suffix == SUFFIXES[0]:
                return "%d%s" % (quantity, suffix)
            else:
                return "%.1f%s" % (quantity, suffix)
        else:
            quantity /= multiple

1

আপনি নীচে যেটি সন্ধান করতে চলেছেন তা ইতিমধ্যে পোস্ট করা ব্যক্তিদের মধ্যে সবচেয়ে পারফরম্যান্স বা সংক্ষিপ্ত সমাধান নয়। পরিবর্তে, এটি একটি নির্দিষ্ট ইস্যুতে কেন্দ্রীভূত করে যা অন্যান্য উত্তরগুলির মধ্যে অনেকগুলি মিস হয়।

যথা যখন ইনপুট লাইক 999_995দেওয়া হয় তখন:

Python 3.6.1 ...
...
>>> value = 999_995
>>> base = 1000
>>> math.log(value, base)
1.999999276174054

যা নিকটতম পূর্ণসংখ্যার সাথে কাটা হয় এবং ইনপুট দেয় তা প্রয়োগ করে

>>> order = int(math.log(value, base))
>>> value/base**order
999.995

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

যথাযথতা 2 টি সংখ্যায় সেট করা সহ আমরা পাই:

>>> round(value/base**order, 2)
1000 # K

পরিবর্তে 1M

কীভাবে আমরা এর মোকাবিলা করতে পারি?

অবশ্যই, আমরা এটি স্পষ্টভাবে পরীক্ষা করতে পারি:

if round(value/base**order, 2) == base:
    order += 1

তবে আমরা কি আরও ভাল করতে পারি? আমরা জানতে কোন পথে পেতে পারি orderআগে আমরা চূড়ান্ত পদক্ষেপ না কাটা করা উচিত?

এটি আমরা করতে পারি।

0.5 দশমিক দশমিক বৃত্তাকার নিয়ম ধরে নেওয়া, উপরের ifশর্তটি এতে অনুবাদ করে:

এখানে চিত্র বর্ণনা লিখুন

ফলস্বরূপ

def abbreviate(value, base=1000, precision=2, suffixes=None):
    if suffixes is None:
        suffixes = ['', 'K', 'M', 'B', 'T']

    if value == 0:
        return f'{0}{suffixes[0]}'

    order_max = len(suffixes) - 1
    order = log(abs(value), base)
    order_corr = order - int(order) >= log(base - 0.5/10**precision, base)
    order = min(int(order) + order_corr, order_max)

    factored = round(value/base**order, precision)

    return f'{factored:,g}{suffixes[order]}'

দান

>>> abbreviate(999_994)
'999.99K'
>>> abbreviate(999_995)
'1M'
>>> abbreviate(999_995, precision=3)
'999.995K'
>>> abbreviate(2042, base=1024)
'1.99K'
>>> abbreviate(2043, base=1024)
'2K'

0

Sridhar Ratnakumarএর উত্তর উল্লেখ করুন , এতে আপডেট হয়েছে:

def formatSize(sizeInBytes, decimalNum=1, isUnitWithI=False, sizeUnitSeperator=""):
  """format size to human readable string"""
  # https://en.wikipedia.org/wiki/Binary_prefix#Specific_units_of_IEC_60027-2_A.2_and_ISO.2FIEC_80000
  # K=kilo, M=mega, G=giga, T=tera, P=peta, E=exa, Z=zetta, Y=yotta
  sizeUnitList = ['','K','M','G','T','P','E','Z']
  largestUnit = 'Y'

  if isUnitWithI:
    sizeUnitListWithI = []
    for curIdx, eachUnit in enumerate(sizeUnitList):
      unitWithI = eachUnit
      if curIdx >= 1:
        unitWithI += 'i'
      sizeUnitListWithI.append(unitWithI)

    # sizeUnitListWithI = ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi']
    sizeUnitList = sizeUnitListWithI

    largestUnit += 'i'

  suffix = "B"
  decimalFormat = "." + str(decimalNum) + "f" # ".1f"
  finalFormat = "%" + decimalFormat + sizeUnitSeperator + "%s%s" # "%.1f%s%s"
  sizeNum = sizeInBytes
  for sizeUnit in sizeUnitList:
      if abs(sizeNum) < 1024.0:
        return finalFormat % (sizeNum, sizeUnit, suffix)
      sizeNum /= 1024.0
  return finalFormat % (sizeNum, largestUnit, suffix)

এবং উদাহরণ আউটপুট হয়:

def testKb():
  kbSize = 3746
  kbStr = formatSize(kbSize)
  print("%s -> %s" % (kbSize, kbStr))

def testI():
  iSize = 87533
  iStr = formatSize(iSize, isUnitWithI=True)
  print("%s -> %s" % (iSize, iStr))

def testSeparator():
  seperatorSize = 98654
  seperatorStr = formatSize(seperatorSize, sizeUnitSeperator=" ")
  print("%s -> %s" % (seperatorSize, seperatorStr))

def testBytes():
  bytesSize = 352
  bytesStr = formatSize(bytesSize)
  print("%s -> %s" % (bytesSize, bytesStr))

def testMb():
  mbSize = 76383285
  mbStr = formatSize(mbSize, decimalNum=2)
  print("%s -> %s" % (mbSize, mbStr))

def testTb():
  tbSize = 763832854988542
  tbStr = formatSize(tbSize, decimalNum=2)
  print("%s -> %s" % (tbSize, tbStr))

def testPb():
  pbSize = 763832854988542665
  pbStr = formatSize(pbSize, decimalNum=4)
  print("%s -> %s" % (pbSize, pbStr))


def demoFormatSize():
  testKb()
  testI()
  testSeparator()
  testBytes()
  testMb()
  testTb()
  testPb()

  # 3746 -> 3.7KB
  # 87533 -> 85.5KiB
  # 98654 -> 96.3 KB
  # 352 -> 352.0B
  # 76383285 -> 72.84MB
  # 763832854988542 -> 694.70TB
  # 763832854988542665 -> 678.4199PB

0

আপনার মন কীভাবে কাজ করে তার উপর নির্ভর করে এই সমাধানটি আপনার কাছে আবেদনও করতে পারে:

from pathlib import Path    

def get_size(path = Path('.')):
    """ Gets file size, or total directory size """
    if path.is_file():
        size = path.stat().st_size
    elif path.is_dir():
        size = sum(file.stat().st_size for file in path.glob('*.*'))
    return size

def format_size(path, unit="MB"):
    """ Converts integers to common size units used in computing """
    bit_shift = {"B": 0,
            "kb": 7,
            "KB": 10,
            "mb": 17,
            "MB": 20,
            "gb": 27,
            "GB": 30,
            "TB": 40,}
    return "{:,.0f}".format(get_size(path) / float(1 << bit_shift[unit])) + " " + unit

# Tests and test results
>>> get_size("d:\\media\\bags of fun.avi")
'38 MB'
>>> get_size("d:\\media\\bags of fun.avi","KB")
'38,763 KB'
>>> get_size("d:\\media\\bags of fun.avi","kb")
'310,104 kb'
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.