J'utilise Python 2.6 sous Linux. Quel est le moyen le plus rapide:
déterminer quelle partition contient un répertoire ou un fichier donné?
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")
.
et ensuite, pour obtenir des statistiques d'utilisation de la partition donnée? Par exemple, étant donné /dev/mapper/foo
J'aimerais obtenir la taille de la partition et l'espace disponible (en octets ou environ en mégaoctets).
Si vous avez juste besoin de l'espace libre sur un périphérique, voir la réponse à l'aide de os.statvfs()
ci-dessous.
Si vous avez également besoin du nom de périphérique et du point de montage associés au fichier, appelez un programme externe pour obtenir ces informations. df
fournira toutes les informations dont vous avez besoin - lorsqu'il est appelé df filename
_ imprime une ligne à propos de la partition contenant 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 ceci est plutôt fragile, car cela dépend du format exact de la sortie df
, mais je ne connais pas de solution plus robuste. (Il existe quelques solutions qui s'appuient sur le /proc
systèmes de fichiers ci-dessous qui sont encore moins portables que celui-ci.)
Cela ne donne pas le nom de la partition, mais vous pouvez obtenir les statistiques du système de fichiers directement à l'aide de l'appel système statvfs
Unix. Pour l'appeler depuis 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 aux valeurs, multipliez 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 de chemins sur mon ordinateur:
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
si on Python ≥3.3, il y a shutil.disk_usage(path)
) qui renvoie un tuple nommé de (total, used, free)
exprimé en octets.
A partir de Python 3.3, il existe un moyen simple et direct de le 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 nombres sont en octets. Voir la documentation pour plus d'informations.
Cela devrait faire tout ce que vous avez demandé:
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 __== '__main__':
for part in disk_partitions():
print part
print " %s\n" % str(disk_usage(part.mountpoint))
Le code ci-dessus est imprimé sur ma boîte:
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)
Le moyen le plus simple de le découvrir.
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, comparez-le avec /etc/mtab
_ (Je suggèrerais même d'appeler getmntent
, mais je ne trouve pas de moyen normal d'y accéder) pour trouver la correspondance la plus longue. (pour être sûr, vous devriez probablement stat
le fichier et le point de montage présumé pour vérifier qu'ils sont bien sur le même périphérique)
Pour le deuxième point, utilisez os.statvfs
pour obtenir des informations sur la taille et l’utilisation des blocs.
(Avertissement: je n'ai testé rien de tout cela, la plupart de ce que je sais provenait des sources de Coreutils)
Pour la deuxième partie de votre question, "obtenir les statistiques d'utilisation de la partition donnée", psutil facilite la tâche avec la fonction disk_usage (path) . Étant donné un chemin, disk_usage()
renvoie un tuple nommé comprenant l'espace total, utilisé et libre exprimé en octets, plus le pourcentage d'utilisation.
Exemple simple tiré de la documentation:
>>> import psutil
>>> psutil.disk_usage('/')
sdiskusage(total=21378641920, used=4809781248, free=15482871808, percent=22.5)
Psutil fonctionne avec Python versions de 2.6 à 3.6 et sous Linux, Windows et OSX, 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')
Généralement, le répertoire _/proc
_ contient ces informations sous Linux, il s’agit d’un système de fichiers virtuel. Par exemple, _/proc/mounts
_ donne des informations sur les disques montés en cours; et vous pouvez l'analyser directement. Des utilitaires comme top
, df
utilisent tous _/proc
_.
Je ne l'ai pas utilisé, mais cela pourrait aussi aider, si vous voulez un wrapper: http://bitbucket.org/chrismiles/psi/wiki/Home