Ich verwende eine Bibliothek, die eine Datei liest und ihre Größe in Bytes zurückgibt.
Diese Dateigröße wird dann dem Endbenutzer angezeigt. Um es ihnen leichter zu machen, es zu verstehen, konvertiere ich die Dateigröße explizit in, indem ich sie MB
durch dividiere 1024.0 * 1024.0
. Natürlich funktioniert das, aber ich frage mich, ob es einen besseren Weg gibt, dies in Python zu tun.
Mit besser meine ich vielleicht eine stdlib-Funktion, die Größen entsprechend dem gewünschten Typ manipulieren kann. Wie wenn ich spezifiziere MB
, teilt es es automatisch durch 1024.0 * 1024.0
. Etwas in diesen Zeilen.
kB (Kilo) for 1.000 Byte
und istKiB (Kibi) for 1.024 Byte
. Siehe en.wikipedia.org/wiki/Kibibyte .Antworten:
Es gibt hurry.filesize , das die Größe in Bytes annimmt und eine schöne Zeichenfolge erstellt, wenn dies der Fall ist .
>>> from hurry.filesize import size >>> size(11000) '10K' >>> size(198283722) '189M'
Oder wenn Sie 1K == 1000 möchten (was die meisten Benutzer annehmen):
>>> from hurry.filesize import size, si >>> size(11000, system=si) '11K' >>> size(198283722, system=si) '198M'
Es hat auch IEC-Unterstützung (aber das wurde nicht dokumentiert):
>>> from hurry.filesize import size, iec >>> size(11000, system=iec) '10Ki' >>> size(198283722, system=iec) '189Mi'
Da der Code von Awesome Martijn Faassen geschrieben wurde, ist er klein, klar und erweiterbar. Das Schreiben eigener Systeme ist kinderleicht.
Hier ist eine:
mysystem = [ (1024 ** 5, ' Megamanys'), (1024 ** 4, ' Lotses'), (1024 ** 3, ' Tons'), (1024 ** 2, ' Heaps'), (1024 ** 1, ' Bunches'), (1024 ** 0, ' Thingies'), ]
So verwendet:
>>> from hurry.filesize import size >>> size(11000, system=mysystem) '10 Bunches' >>> size(198283722, system=mysystem) '189 Heaps'
quelle
1024
(ein int).MBFACTOR = float(1 << 20); mb= int(size_in_bytes) / MBFACTOR
@LennartRegebroFolgendes benutze ich:
import math def convert_size(size_bytes): if size_bytes == 0: return "0B" size_name = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB") i = int(math.floor(math.log(size_bytes, 1024))) p = math.pow(1024, i) s = round(size_bytes / p, 2) return "%s %s" % (s, size_name[i])
NB: Die Größe sollte in Bytes gesendet werden.
quelle
Anstelle eines Größenteilers von
1024 * 1024
Ihnen könnten Sie den<<
bitweisen Verschiebungsoperator verwenden , dh1<<20
um Megabytes,1<<30
Gigabytes usw. zu erhalten.Im einfachsten Szenario können Sie zB eine Konstante haben,
MBFACTOR = float(1<<20)
die dann mit Bytes verwendet werden kann, dh :megas = size_in_bytes/MBFACTOR
.Megabyte sind normalerweise alles, was Sie brauchen, oder auf andere Weise kann so etwas verwendet werden:
# bytes pretty-printing UNITS_MAPPING = [ (1<<50, ' PB'), (1<<40, ' TB'), (1<<30, ' GB'), (1<<20, ' MB'), (1<<10, ' KB'), (1, (' byte', ' bytes')), ] def pretty_size(bytes, units=UNITS_MAPPING): """Get human-readable file sizes. simplified version of https://pypi.python.org/pypi/hurry.filesize/ """ for factor, suffix in units: if bytes >= factor: break amount = int(bytes / factor) if isinstance(suffix, tuple): singular, multiple = suffix if amount == 1: suffix = singular else: suffix = multiple return str(amount) + suffix print(pretty_size(1)) print(pretty_size(42)) print(pretty_size(4096)) print(pretty_size(238048577)) print(pretty_size(334073741824)) print(pretty_size(96995116277763)) print(pretty_size(3125899904842624)) ## [Out] ########################### 1 byte 42 bytes 4 KB 227 MB 311 GB 88 TB 2 PB
quelle
>>
?0
.Hier ist die kompakte Funktion zur Berechnung der Größe
def GetHumanReadable(size,precision=2): suffixes=['B','KB','MB','GB','TB'] suffixIndex = 0 while size > 1024 and suffixIndex < 4: suffixIndex += 1 #increment the index of the suffix size = size/1024.0 #apply the division return "%.*f%s"%(precision,size,suffixes[suffixIndex])
Weitere Informationen zur Ausgabe und umgekehrt finden Sie unter: http://code.activestate.com/recipes/578019-bytes-to-human-human-to-bytes-converter/
quelle
Im Folgenden finden Sie eine schnelle und relativ einfach zu lesende Methode zum Drucken von Dateigrößen in einer einzigen Codezeile, wenn Sie bereits wissen, was Sie möchten. Diese Einzeiler kombinieren die großartige Antwort von @ccpizza oben mit einigen praktischen Formatierungstricks, die ich hier gelesen habe. Wie drucke ich Zahlen mit Kommas als Tausendertrennzeichen? .
Bytes
print ('{:,.0f}'.format(os.path.getsize(filepath))+" B")
Kilobits
print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<7))+" kb")
Kilobyte
print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<10))+" KB")
Megabits
print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<17))+" mb")
Megabyte
print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<20))+" MB")
Gigabit
print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<27))+" gb")
Gigabyte
print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<30))+" GB")
Terabyte
print ('{:,.0f}'.format(os.path.getsize(filepath)/float(1<<40))+" TB")
Offensichtlich gehen sie davon aus, dass Sie ungefähr wissen, mit welcher Größe Sie zu Beginn zu tun haben. In meinem Fall (Video-Editor bei South West London TV) ist dies MB und gelegentlich GB für Videoclips.
UPDATE MIT PATHLIB Als Antwort auf Hildys Kommentar ist hier mein Vorschlag für ein kompaktes Funktionspaar (Dinge "atomar" halten, anstatt sie zusammenzuführen), das nur die Python-Standardbibliothek verwendet:
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 >>> format_size("d:\\media\\bags of fun.avi") '38 MB' >>> format_size("d:\\media\\bags of fun.avi","KB") '38,763 KB' >>> format_size("d:\\media\\bags of fun.avi","kb") '310,104 kb'
quelle
Nur für den Fall, dass jemand nach der Umkehrung dieses Problems sucht (wie ich es sicher getan habe), funktioniert Folgendes für mich:
def get_bytes(size, suffix): size = int(float(size)) suffix = suffix.lower() if suffix == 'kb' or suffix == 'kib': return size << 10 elif suffix == 'mb' or suffix == 'mib': return size << 20 elif suffix == 'gb' or suffix == 'gib': return size << 30 return False
quelle
<< 10
zu* 1024
,<< 20
zu* 1024**2
und<< 30
zu* 1024**3
.Hier ist es:
def convert_bytes(size): for x in ['bytes', 'KB', 'MB', 'GB', 'TB']: if size < 1024.0: return "%3.1f %s" % (size, x) size /= 1024.0 return size
quelle
Hier meine zwei Cent, die das Auf- und Abwerfen ermöglichen und anpassbare Präzision hinzufügen:
def convertFloatToDecimal(f=0.0, precision=2): ''' Convert a float to string of decimal. precision: by default 2. If no arg provided, return "0.00". ''' return ("%." + str(precision) + "f") % f def formatFileSize(size, sizeIn, sizeOut, precision=0): ''' Convert file size to a string representing its value in B, KB, MB and GB. The convention is based on sizeIn as original unit and sizeOut as final unit. ''' assert sizeIn.upper() in {"B", "KB", "MB", "GB"}, "sizeIn type error" assert sizeOut.upper() in {"B", "KB", "MB", "GB"}, "sizeOut type error" if sizeIn == "B": if sizeOut == "KB": return convertFloatToDecimal((size/1024.0), precision) elif sizeOut == "MB": return convertFloatToDecimal((size/1024.0**2), precision) elif sizeOut == "GB": return convertFloatToDecimal((size/1024.0**3), precision) elif sizeIn == "KB": if sizeOut == "B": return convertFloatToDecimal((size*1024.0), precision) elif sizeOut == "MB": return convertFloatToDecimal((size/1024.0), precision) elif sizeOut == "GB": return convertFloatToDecimal((size/1024.0**2), precision) elif sizeIn == "MB": if sizeOut == "B": return convertFloatToDecimal((size*1024.0**2), precision) elif sizeOut == "KB": return convertFloatToDecimal((size*1024.0), precision) elif sizeOut == "GB": return convertFloatToDecimal((size/1024.0), precision) elif sizeIn == "GB": if sizeOut == "B": return convertFloatToDecimal((size*1024.0**3), precision) elif sizeOut == "KB": return convertFloatToDecimal((size*1024.0**2), precision) elif sizeOut == "MB": return convertFloatToDecimal((size*1024.0), precision)
Fügen Sie
TB
usw. hinzu, wie Sie möchten.quelle
Hier ist eine Version, die der Ausgabe von ls -lh entspricht .
def human_size(num: int) -> str: base = 1 for unit in ['B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']: n = num / base if n < 9.95 and unit != 'B': # Less than 10 then keep 1 decimal place value = "{:.1f}{}".format(n, unit) return value if round(n) < 1000: # Less than 4 digits so use this value = "{}{}".format(round(n), unit) return value base *= 1024 value = "{}{}".format(round(n), unit) return value
quelle
UNITS = {1000: ['KB', 'MB', 'GB'], 1024: ['KiB', 'MiB', 'GiB']} def approximate_size(size, flag_1024_or_1000=True): mult = 1024 if flag_1024_or_1000 else 1000 for unit in UNITS[mult]: size = size / mult if size < mult: return '{0:.3f} {1}'.format(size, unit) approximate_size(2123, False)
quelle
Hier ist meine Implementierung:
from bisect import bisect def to_filesize(bytes_num, si=True): decade = 1000 if si else 1024 partitions = tuple(decade ** n for n in range(1, 6)) suffixes = tuple('BKMGTP') i = bisect(partitions, bytes_num) s = suffixes[i] for n in range(i): bytes_num /= decade f = '{:.3f}'.format(bytes_num) return '{}{}'.format(f.rstrip('0').rstrip('.'), s)
Es werden bis zu drei Dezimalstellen gedruckt und nachgestellte Nullen und Punkte entfernt. Der boolesche Parameter
si
schaltet die Verwendung der 10-basierten gegenüber der 2-basierten Größengröße um.Dies ist sein Gegenstück. Es ermöglicht das Schreiben sauberer Konfigurationsdateien wie
{'maximum_filesize': from_filesize('10M')
. Es wird eine Ganzzahl zurückgegeben, die sich der beabsichtigten Dateigröße annähert. Ich verwende keine Bitverschiebung, da der Quellwert eine Gleitkommazahl ist (es wird gut akzeptiertfrom_filesize('2.15M')
). Das Konvertieren in eine Ganzzahl / Dezimalzahl würde funktionieren, macht den Code jedoch komplizierter und funktioniert bereits so wie er ist.def from_filesize(spec, si=True): decade = 1000 if si else 1024 suffixes = tuple('BKMGTP') num = float(spec[:-1]) s = spec[-1] i = suffixes.index(s) for n in range(i): num *= decade return int(num)
quelle
Hier ist eine weitere Version der umgekehrten Implementierung von @ romeo, die eine einzelne Eingabezeichenfolge verarbeitet.
import re def get_bytes(size_string): try: size_string = size_string.lower().replace(',', '') size = re.search('^(\d+)[a-z]i?b$', size_string).groups()[0] suffix = re.search('^\d+([kmgtp])i?b$', size_string).groups()[0] except AttributeError: raise ValueError("Invalid Input") shft = suffix.translate(str.maketrans('kmgtp', '12345')) + '0' return int(size) << int(shft)
quelle
Ähnlich wie Aaron Dukes Antwort, aber eher "pythonisch";)
import re RE_SIZE = re.compile(r'^(\d+)([a-z])i?b?$') def to_bytes(s): parts = RE_SIZE.search(s.lower().replace(',', '')) if not parts: raise ValueError("Invalid Input") size = parts.group(1) suffix = parts.group(2) shift = suffix.translate(str.maketrans('kmgtp', '12345')) + '0' return int(size) << int(shift)
quelle
Ich bin neu in der Programmierung. Ich habe mir diese folgende Funktion ausgedacht, die eine bestimmte Dateigröße in ein lesbares Format konvertiert.
def file_size_converter(size): magic = lambda x: str(round(size/round(x/1024), 2)) size_in_int = [int(1 << 10), int(1 << 20), int(1 << 30), int(1 << 40), int(1 << 50)] size_in_text = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] for i in size_in_int: if size < i: g = size_in_int.index(i) position = int((1024 % i) / 1024 * g) ss = magic(i) return ss + ' ' + size_in_text[position]
quelle
Dies funktioniert korrekt für alle Dateigrößen:
import math from os.path import getsize def convert_size(size): if (size == 0): return '0B' size_name = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB") i = int(math.floor(math.log(size,1024))) p = math.pow(1024,i) s = round(size/p,2) return '%s %s' % (s,size_name[i]) print(convert_size(getsize('file_name.zip')))
quelle