Trouvez la taille et de l'espace libre du système de fichiers contenant un fichier donné
-
27-09-2019 - |
Question
J'utilise Python 2.6 sous Linux. Quelle est la façon la plus rapide:
-
pour déterminer quelle partition contient un répertoire donné ou d'un fichier?
Par exemple, supposons que
/dev/sda2
est monté sur/home
et/dev/mapper/foo
est monté sur/home/foo
. De la chaîne"/home/foo/bar/baz"
je voudrais récupérer la paire("/dev/mapper/foo", "home/foo")
. -
puis, pour obtenir des statistiques d'utilisation de la partition donnée? Par exemple, étant donné
/dev/mapper/foo
je voudrais obtenir la taille de la partition et l'espace libre disponible (soit en octets, soit environ en méga-octets).
La solution
Si vous avez juste besoin de l'espace libre sur un appareil, voir la réponse à l'aide os.statvfs()
ci-dessous.
Si vous avez également besoin le nom du périphérique et point de montage associé au fichier, vous devez appeler un programme externe pour obtenir cette information. df
fournira toutes les informations dont vous avez besoin -. quand appelé df filename
il imprime une ligne de la partition qui contient le fichier
Pour donner un exemple:
import subprocess
df = subprocess.Popen(["df", "filename"], stdout=subprocess.PIPE)
output = df.communicate()[0]
device, size, used, available, percent, mountpoint = \
output.split("\n")[1].split()
Notez que cela est assez fragile, car elle dépend du format exact de la sortie df
, mais je ne suis pas au courant d'une solution plus robuste. (Il y a quelques solutions reposant sur le système de fichiers /proc
ci-dessous qui sont encore moins portable que celui-ci.)
Autres conseils
Cela ne donne pas le nom de la partition, mais vous pouvez obtenir les statistiques du système de fichiers en utilisant directement l'appel système Unix statvfs
. Pour appeler à partir de Python, utilisez os.statvfs('/home/foo/bar/baz')
.
Les champs pertinents dans le résultat, selon POSIX :
unsigned long f_frsize Fundamental file system block size. fsblkcnt_t f_blocks Total number of blocks on file system in units of f_frsize. fsblkcnt_t f_bfree Total number of free blocks. fsblkcnt_t f_bavail Number of free blocks available to non-privileged process.
Donc, pour donner un sens des valeurs, il faut multiplier par f_frsize
:
import os
statvfs = os.statvfs('/home/foo/bar/baz')
statvfs.f_frsize * statvfs.f_blocks # Size of filesystem in bytes
statvfs.f_frsize * statvfs.f_bfree # Actual number of free bytes
statvfs.f_frsize * statvfs.f_bavail # Number of free bytes that ordinary users
# are allowed to use (excl. reserved space)
import os
def get_mount_point(pathname):
"Get the mount point of the filesystem containing pathname"
pathname= os.path.normcase(os.path.realpath(pathname))
parent_device= path_device= os.stat(pathname).st_dev
while parent_device == path_device:
mount_point= pathname
pathname= os.path.dirname(pathname)
if pathname == mount_point: break
parent_device= os.stat(pathname).st_dev
return mount_point
def get_mounted_device(pathname):
"Get the device mounted at pathname"
# uses "/proc/mounts"
pathname= os.path.normcase(pathname) # might be unnecessary here
try:
with open("/proc/mounts", "r") as ifp:
for line in ifp:
fields= line.rstrip('\n').split()
# note that line above assumes that
# no mount points contain whitespace
if fields[1] == pathname:
return fields[0]
except EnvironmentError:
pass
return None # explicit
def get_fs_freespace(pathname):
"Get the free space of the filesystem containing pathname"
stat= os.statvfs(pathname)
# use f_bfree for superuser, or f_bavail if filesystem
# has reserved space for superuser
return stat.f_bfree*stat.f_bsize
Quelques exemples sur mon ordinateur noms de fichiers:
path 'trash':
mp /home /dev/sda4
free 6413754368
path 'smov':
mp /mnt/S /dev/sde
free 86761562112
path '/usr/local/lib':
mp / rootfs
free 2184364032
path '/proc/self/cmdline':
mp /proc proc
free 0
PS
si sur Python ≥3.3, il y a shutil.disk_usage(path)
qui retourne un tuple de nom (total, used, free)
exprimé en octets.
de Python 3.3, il un moyen facile et direct à faire avec la bibliothèque standard:
$ cat free_space.py
#!/usr/bin/env python3
import shutil
total, used, free = shutil.disk_usage(__file__)
print(total, used, free)
$ ./free_space.py
1007870246912 460794834944 495854989312
Ces chiffres sont en octets. Voir la documentation pour plus d'informations.
Cela devrait tout faire vous demande:
import os
from collections import namedtuple
disk_ntuple = namedtuple('partition', 'device mountpoint fstype')
usage_ntuple = namedtuple('usage', 'total used free percent')
def disk_partitions(all=False):
"""Return all mountd partitions as a nameduple.
If all == False return phyisical partitions only.
"""
phydevs = []
f = open("/proc/filesystems", "r")
for line in f:
if not line.startswith("nodev"):
phydevs.append(line.strip())
retlist = []
f = open('/etc/mtab', "r")
for line in f:
if not all and line.startswith('none'):
continue
fields = line.split()
device = fields[0]
mountpoint = fields[1]
fstype = fields[2]
if not all and fstype not in phydevs:
continue
if device == 'none':
device = ''
ntuple = disk_ntuple(device, mountpoint, fstype)
retlist.append(ntuple)
return retlist
def disk_usage(path):
"""Return disk usage associated with path."""
st = os.statvfs(path)
free = (st.f_bavail * st.f_frsize)
total = (st.f_blocks * st.f_frsize)
used = (st.f_blocks - st.f_bfree) * st.f_frsize
try:
percent = ret = (float(used) / total) * 100
except ZeroDivisionError:
percent = 0
# NB: the percentage is -5% than what shown by df due to
# reserved blocks that we are currently not considering:
# http://goo.gl/sWGbH
return usage_ntuple(total, used, free, round(percent, 1))
if __name__ == '__main__':
for part in disk_partitions():
print part
print " %s\n" % str(disk_usage(part.mountpoint))
Sur ma boîte le code ci-dessus impressions:
giampaolo@ubuntu:~/dev$ python foo.py
partition(device='/dev/sda3', mountpoint='/', fstype='ext4')
usage(total=21378641920, used=4886749184, free=15405903872, percent=22.9)
partition(device='/dev/sda7', mountpoint='/home', fstype='ext4')
usage(total=30227386368, used=12137168896, free=16554737664, percent=40.2)
partition(device='/dev/sdb1', mountpoint='/media/1CA0-065B', fstype='vfat')
usage(total=7952400384, used=32768, free=7952367616, percent=0.0)
partition(device='/dev/sr0', mountpoint='/media/WB2PFRE_IT', fstype='iso9660')
usage(total=695730176, used=695730176, free=0, percent=100.0)
partition(device='/dev/sda6', mountpoint='/media/Dati', fstype='fuseblk')
usage(total=914217758720, used=614345637888, free=299872120832, percent=67.2)
La façon la plus simple de savoir ce.
import os
from collections import namedtuple
DiskUsage = namedtuple('DiskUsage', 'total used free')
def disk_usage(path):
"""Return disk usage statistics about the given path.
Will return the namedtuple with attributes: 'total', 'used' and 'free',
which are the amount of total, used and free space, in bytes.
"""
st = os.statvfs(path)
free = st.f_bavail * st.f_frsize
total = st.f_blocks * st.f_frsize
used = (st.f_blocks - st.f_bfree) * st.f_frsize
return DiskUsage(total, used, free)
Pour le premier point, vous pouvez essayer d'utiliser os.path.realpath
pour obtenir un chemin canonique, vérifiez contre /etc/mtab
(je vous suggère d'appeler effectivement getmntent
, mais je ne peux pas trouver un moyen normal d'y accéder) pour trouver le plus long match. (Pour être sûr, vous devriez probablement stat
à la fois le fichier et le point de montage présumé vérifier qu'ils sont en fait sur le même appareil)
Pour le deuxième point, utilisez os.statvfs
pour obtenir la taille de bloc et informations sur l'utilisation.
(Disclaimer: Je l'ai testé rien de tout cela, la plupart de ce que je sais est venu des sources coreutils)
Pour la deuxième partie de votre question, "obtenir des statistiques d'utilisation de la partition donnée", psutil facilite la tâche avec le disk_usage (chemin) fonction . Compte tenu d'un chemin, disk_usage()
retourne un tuple nom comprenant au total, utilisé et l'espace libre en octets, plus le pourcentage d'utilisation.
Exemple simple de la documentation:
>>> import psutil
>>> psutil.disk_usage('/')
sdiskusage(total=21378641920, used=4809781248, free=15482871808, percent=22.5)
psutil fonctionne avec les versions Python de 2,6 à 3,6 et sous Linux, Windows et Mac OS X entre autres plates-formes.
import os
def disk_stat(path):
disk = os.statvfs(path)
percent = (disk.f_blocks - disk.f_bfree) * 100 / (disk.f_blocks -disk.f_bfree + disk.f_bavail) + 1
return percent
print disk_stat('/')
print disk_stat('/data')
En général, le répertoire contient /proc
ces informations sous Linux, il est un système de fichiers virtuel. Par exemple, /proc/mounts
donne des informations sur les disques montés en cours; et vous pouvez analyser directement. Des utilitaires comme top
, df
tout faire usage de /proc
.
Je l'ai pas utilisé, mais cela pourrait aider aussi, si vous voulez un emballage: http : //bitbucket.org/chrismiles/psi/wiki/Home