Voici quelques modèles faciles à copier que vous pouvez utiliser si vous connaissez déjà la taille de l'unité que vous souhaitez. Si vous recherchez une fonction plus générique avec quelques options intéressantes, consultez ma mise à jour de FEB 2021 plus loin...
Octets
print(f"{os.path.getsize(filepath):,} B")
Kilobits
print(f"{os.path.getsize(filepath)/(1<<7):,.0f} kb")
Kilo-octets
print(f"{os.path.getsize(filepath)/(1<<10):,.0f} KB")
Mégabits
print(f"{os.path.getsize(filepath)/(1<<17):,.0f} mb")
Mégaoctets
print(f"{os.path.getsize(filepath)/(1<<20):,.0f} MB")
Gigabits
print(f"{os.path.getsize(filepath)/(1<<27):,.0f} gb")
Gigaoctets
print(f"{os.path.getsize(filepath)/(1<<30):,.0f} GB")
Téraoctets
print(f"{os.path.getsize(filepath)/(1<<40):,.0f} TB")
MISE À JOUR FEB 2021 Voici mes fonctions mises à jour et étoffées pour a) obtenir la taille d'un fichier/dossier, b) convertir dans les unités souhaitées :
from pathlib import Path
def get_path_size(path = Path('.'), recursive=False):
"""
Gets file size, or total directory size
Parameters
----------
path: str | pathlib.Path
File path or directory/folder path
recursive: bool
True -> use .rglob i.e. include nested files and directories
False -> use .glob i.e. only process current directory/folder
Returns
-------
int:
File size or recursive directory size in bytes
Use cleverutils.format_bytes to convert to other units e.g. MB
"""
path = Path(path)
if path.is_file():
size = path.stat().st_size
elif path.is_dir():
path_glob = path.rglob('*.*') if recursive else path.glob('*.*')
size = sum(file.stat().st_size for file in path_glob)
return size
def format_bytes(bytes, unit, SI=False):
"""
Converts bytes to common units such as kb, kib, KB, mb, mib, MB
Parameters
---------
bytes: int
Number of bytes to be converted
unit: str
Desired unit of measure for output
SI: bool
True -> Use SI standard e.g. KB = 1000 bytes
False -> Use JEDEC standard e.g. KB = 1024 bytes
Returns
-------
str:
E.g. "7 MiB" where MiB is the original unit abbreviation supplied
"""
if unit.lower() in "b bit bits".split():
return f"{bytes*8} {unit}"
unitN = unit[0].upper()+unit[1:].replace("s","") # Normalised
reference = {"Kb Kib Kibibit Kilobit": (7, 1),
"KB KiB Kibibyte Kilobyte": (10, 1),
"Mb Mib Mebibit Megabit": (17, 2),
"MB MiB Mebibyte Megabyte": (20, 2),
"Gb Gib Gibibit Gigabit": (27, 3),
"GB GiB Gibibyte Gigabyte": (30, 3),
"Tb Tib Tebibit Terabit": (37, 4),
"TB TiB Tebibyte Terabyte": (40, 4),
"Pb Pib Pebibit Petabit": (47, 5),
"PB PiB Pebibyte Petabyte": (50, 5),
"Eb Eib Exbibit Exabit": (57, 6),
"EB EiB Exbibyte Exabyte": (60, 6),
"Zb Zib Zebibit Zettabit": (67, 7),
"ZB ZiB Zebibyte Zettabyte": (70, 7),
"Yb Yib Yobibit Yottabit": (77, 8),
"YB YiB Yobibyte Yottabyte": (80, 8),
}
key_list = '\n'.join([" b Bit"] + [x for x in reference.keys()]) +"\n"
if unitN not in key_list:
raise IndexError(f"\n\nConversion unit must be one of:\n\n{key_list}")
units, divisors = [(k,v) for k,v in reference.items() if unitN in k][0]
if SI:
divisor = 1000**divisors[1]/8 if "bit" in units else 1000**divisors[1]
else:
divisor = float(1 << divisors[0])
value = bytes / divisor
return f"{value:,.0f} {unitN}{(value != 1 and len(unitN) > 3)*'s'}"
# Tests
>>> assert format_bytes(1,"b") == '8 b'
>>> assert format_bytes(1,"bits") == '8 bits'
>>> assert format_bytes(1024, "kilobyte") == "1 Kilobyte"
>>> assert format_bytes(1024, "kB") == "1 KB"
>>> assert format_bytes(7141000, "mb") == '54 Mb'
>>> assert format_bytes(7141000, "mib") == '54 Mib'
>>> assert format_bytes(7141000, "Mb") == '54 Mb'
>>> assert format_bytes(7141000, "MB") == '7 MB'
>>> assert format_bytes(7141000, "mebibytes") == '7 Mebibytes'
>>> assert format_bytes(7141000, "gb") == '0 Gb'
>>> assert format_bytes(1000000, "kB") == '977 KB'
>>> assert format_bytes(1000000, "kB", SI=True) == '1,000 KB'
>>> assert format_bytes(1000000, "kb") == '7,812 Kb'
>>> assert format_bytes(1000000, "kb", SI=True) == '8,000 Kb'
>>> assert format_bytes(125000, "kb") == '977 Kb'
>>> assert format_bytes(125000, "kb", SI=True) == '1,000 Kb'
>>> assert format_bytes(125*1024, "kb") == '1,000 Kb'
>>> assert format_bytes(125*1024, "kb", SI=True) == '1,024 Kb'
MISE À JOUR OCT 2022
_Ma réponse à un commentaire récent était trop longue, alors voici quelques explications supplémentaires sur la magie 1<<20 ! Je remarque également que flotteur n'est pas nécessaire, je l'ai donc supprimé des exemples ci-dessus._
Comme indiqué dans une autre réponse (ci-dessus), "<<" est appelé un "opérateur bitwise". Il convertit le côté gauche en binaire et déplace les chiffres binaires de 20 places vers la gauche (dans ce cas). Lorsque nous comptons normalement en décimal, le nombre total de chiffres indique si nous avons atteint les dizaines, les centaines, les milliers, les millions, etc. C'est la même chose en binaire, sauf que le nombre de chiffres indique s'il s'agit de bits, d'octets, de kilo-octets, de méga-octets, etc. Ainsi, .... 1<<20 est en fait la même chose que le 1 (binaire) suivi de 20 zéros (binaires) ou, si vous vous souvenez de la conversion du binaire au décimal : 2 à la puissance 20 (2**20), ce qui équivaut à 1048576. Dans les extraits ci-dessus, os.path.getsize renvoie une valeur en BYTES et 1048576 octets correspondent strictement à un Mébibyte (MiB) et plus couramment à un Mégaoctet (MB).