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).

Était-ce utile?

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top