वेब पर विभिन्न स्निपेट्स हैं जो आपको बाइट्स आकार से मानव पठनीय आकार को वापस करने के लिए एक फ़ंक्शन देंगे:
>>> human_readable(2048)
'2 kilobytes'
>>>
लेकिन क्या एक पायथन पुस्तकालय है जो इसे प्रदान करता है?
वेब पर विभिन्न स्निपेट्स हैं जो आपको बाइट्स आकार से मानव पठनीय आकार को वापस करने के लिए एक फ़ंक्शन देंगे:
>>> human_readable(2048)
'2 kilobytes'
>>>
लेकिन क्या एक पायथन पुस्तकालय है जो इसे प्रदान करता है?
जवाबों:
उपरोक्त "संबोधित करने के लिए एक कार्य के लिए एक पुस्तकालय की आवश्यकता के लिए बहुत छोटा काम" एक सीधा कार्यान्वयन द्वारा मुद्दा:
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)
समर्थन:
उदाहरण:
>>> sizeof_fmt(168963795964)
'157.4GiB'
फ्रेड सेरा द्वारा
B
(बाइट्स के अलावा अन्य इकाइयों के लिए) के 1000.0
बजाय आप चाहते हैं कि कारक 1024.0
नहीं के बजाय होगा ?
1
जो भी परिशुद्धता चाहते हैं, उसे लाइनों ४ और ६ पर बदल दें।
एक पुस्तकालय जिसमें वह सभी कार्यक्षमता होती है जो ऐसा लगता है कि आप खोज रहे हैं humanize
। humanize.naturalsize()
लगता है कि सब कुछ आप के लिए देख रहे हैं।
humanize.naturalsize(2048) # => '2.0 kB'
,humanize.naturalsize(2048, binary=True) # => '2.0 KiB'
humanize.naturalsize(2048, gnu=True) # => '2.0K'
यहाँ मेरा संस्करण है। यह फॉर-लूप का उपयोग नहीं करता है। इसमें निरंतर जटिलता है, ओ ( 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]
1000
जैसा दिखाई देगा 1,000 bytes
।
unit_list = list(zip(['bytes', 'kB', 'MB', 'GB', 'TB', 'PB'], [0, 0, 1, 2, 2, 2]))
पायथन 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}"
जबकि मुझे पता है कि यह सवाल प्राचीन है, मैं हाल ही में एक संस्करण के साथ आया था जो लूप से बचा जाता है, 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])
अच्छी तरह से अपनी पठनीयता के लिए अनहोनी माना जा सकता है, हालांकि :)
size
या (1 << (order * 10)
में float()
अंतिम पंक्ति (अजगर 2 के लिए) में।
import math
वहाँ की आवश्यकता हो सकती है ।
वहाँ हमेशा उन लोगों में से एक हो गया है। खैर आज यह मैं हूँ। यदि आप फ़ंक्शन हस्ताक्षर की गणना करते हैं तो यहां एक-लाइनर समाधान - या दो लाइनें हैं।
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
units=None
के बजाय)
यदि आप Django स्थापित का उपयोग कर रहे हैं, तो आप filesizeformat भी आज़मा सकते हैं :
from django.template.defaultfilters import filesizeformat
filesizeformat(1073741824)
=>
"1.0 GB"
ऐसी ही एक लाइब्रेरी है जल्दबाज़ी ।
>>> from hurry.filesize import alternative
>>> size(1, system=alternative)
'1 byte'
>>> size(10, system=alternative)
'10 bytes'
>>> size(1024, system=alternative)
'1 KB'
1000 या kibibytes की शक्तियों का उपयोग करना अधिक मानक-अनुकूल होगा:
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)
PS कभी भी उस लाइब्रेरी पर भरोसा नहीं करता जो K (अपरकेस) प्रत्यय के साथ हजारों प्रिंट करता है :)
P.S. Never trust a library that prints thousands with the K (uppercase) suffix :)
क्यों नहीं? कोड पूरी तरह से ध्वनि हो सकता है और लेखक सिर्फ किलो के लिए आवरण पर विचार नहीं करता है। यह आपके नियम के आधार पर किसी भी कोड को स्वचालित रूप से खारिज करने के लिए बहुत ही सुंदर लगता है ...
यह वही करेगा जो आपको लगभग किसी भी स्थिति में चाहिए, वैकल्पिक तर्क के साथ अनुकूलन योग्य है, और जैसा कि आप देख सकते हैं, बहुत अधिक स्व-दस्तावेजीकरण है:
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 दोनों संगत है। PEP8 अनुपालन पाठक के लिए एक अभ्यास है। याद रखें, यह है उत्पादन सुंदर है कि।
अपडेट करें:
यदि आपको हजारों अल्पविरामों की आवश्यकता है, तो बस स्पष्ट एक्सटेंशन लागू करें:
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'
आपको "मानवीकरण" का उपयोग करना चाहिए।
>>> humanize.naturalsize(1000000)
'1.0 MB'
>>> humanize.naturalsize(1000000, binary=True)
'976.6 KiB'
>>> humanize.naturalsize(1000000, gnu=True)
'976.6K'
संदर्भ:
जल्दी करने के लिए एक विकल्प के रूप में प्रदान की गई स्निपेट पर रिफ़िंग करना (फ़ाइलिज़ करना), यहाँ एक स्निपेट है जो प्रयुक्त उपसर्ग के आधार पर अलग-अलग सटीक संख्या देता है। यह कुछ स्निपेट्स की तरह नहीं है, लेकिन मुझे इसके परिणाम पसंद हैं।
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)
HumanFriendly परियोजना में मदद करता है इस के साथ ।
import humanfriendly
humanfriendly.format_size(1024)
उपरोक्त कोड उत्तर के रूप में 1KB देगा।
उदाहरण यहां देखे जा सकते हैं ।
पिछले सभी उत्तरों से आकर्षित, यहाँ मेरा इस पर ध्यान है। यह एक ऑब्जेक्ट है जो एक पूर्णांक के रूप में बाइट्स में फ़ाइल का आकार संग्रहीत करेगा। लेकिन जब आप ऑब्जेक्ट को प्रिंट करने का प्रयास करते हैं, तो आपको स्वचालित रूप से एक मानव पठनीय संस्करण मिलता है।
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)
मुझे प्रेषक के दशमलव संस्करण की निश्चित सटीकता पसंद है , इसलिए यहां जोक्टी के उत्तर के साथ एक प्रकार का हाइब्रिड है (क्या आप जानते हैं कि आप गैर-पूर्णांक आधारों के साथ लॉग ले सकते हैं?)।
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')
DiveIntoPython3 भी बात करती है इस समारोह के बारे में।
आधुनिक Django के स्वयं टेम्पलेट टैग हैं filesizeformat
:
human-readable
फ़ाइल आकार (जैसे '13 KB ',' 4.1 MB ',' 102 बाइट्स, इत्यादि ') का मूल्य निर्धारित करता है।
उदाहरण के लिए:
{{ value|filesizeformat }}
यदि मान 123456789 है, तो उत्पादन 117.7 एमबी होगा।
अधिक जानकारी: https://docs.djangoproject.com/en/1.10/ref/templates/builtins/#files/formformat
कैसे एक साधारण 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])
यहाँ यह हुड के तहत काम करता है:
Kb
, इसलिए उत्तर X KiB होना चाहिए)file_size/value_of_closest_unit
यूनिट के साथ रिटर्न ।हालाँकि यह काम नहीं करता है यदि फ़ाइल 0 या नकारात्मक है (क्योंकि लॉग 0 और -ve संख्या के लिए अपरिभाषित है)। आप उनके लिए अतिरिक्त जांच जोड़ सकते हैं:
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'
नोट - Kb और KiB में अंतर है। KB का मतलब 1000 बाइट्स है, जबकि KiB का मतलब 1024 बाइट्स है। KB, MB, GB सभी 1000 के गुणक हैं, जबकि KiB, MiB, GiB आदि 1024 के सभी गुणक हैं। यहाँ के बारे में अधिक
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
नीचे आप जो खोजने जा रहे हैं, वह पहले से ही पोस्ट किए गए लोगों के बीच सबसे अच्छा प्रदर्शन या सबसे कम समाधान है। इसके बजाय, यह एक विशेष मुद्दे पर केंद्रित है, जिसमें से कई अन्य उत्तर याद आते हैं।
जब इनपुट 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'
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
यह समाधान भी आपसे अपील कर सकता है, यह निर्भर करता है कि आपका मन कैसे काम करता है:
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'