Найти размер и свободное пространство файловой системы, содержащей данный файл

Я использую Python 2.6 в Linux. Какой самый быстрый способ:

  • определить, какой раздел содержит данный каталог или файл?

    Например, предположим, что /dev/sda2 установлен на /home, а также /dev/mapper/foo установлен на /home/foo, Из строки "/home/foo/bar/baz" Я хотел бы восстановить пару ("/dev/mapper/foo", "home/foo"),

  • а затем, чтобы получить статистику использования данного раздела? Например, учитывая /dev/mapper/foo Я хотел бы получить размер раздела и доступное свободное пространство (в байтах или приблизительно в мегабайтах).

12 ответов

Решение

Если вам просто нужно свободное место на устройстве, посмотрите ответ, используя os.statvfs() ниже.

Если вам также необходимо имя устройства и точка монтирования, связанные с файлом, вам следует вызвать внешнюю программу для получения этой информации. df предоставит всю необходимую информацию - при вызове df filename он печатает строку о разделе, содержащем файл.

Чтобы привести пример:

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

Обратите внимание, что это довольно хрупко, так как это зависит от точного формата df вывод, но я не знаю о более надежном решении. (Есть несколько решений, основанных на /proc файловая система ниже, которая еще менее переносима, чем эта.)

Это не дает имя раздела, но вы можете получить статистику файловой системы непосредственно с помощью statvfs Unix системный вызов. Чтобы вызвать его из Python, используйте os.statvfs('/home/foo/bar/baz'),

Соответствующие поля в результате, в соответствии с 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.

Чтобы понять значения, умножьте на 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)

Начиная с Python 3.3, есть простой и прямой способ сделать это с помощью стандартной библиотеки:

$ 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

Эти числа в байтах. Смотрите документацию для получения дополнительной информации.

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

Некоторые примеры путей на моем компьютере:

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

если на Python ≥3.3, есть shutil.disk_usage(path) который возвращает именованный кортеж (total, used, free) выражается в байтах.

Это должно сделать все, что вы просили:

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

На моей коробке напечатан код выше:

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)

Самый простой способ узнать это.

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)

Для второй части вашего вопроса, "получить статистику использования данного раздела", psutil облегчает это с помощью функции disk_usage(path). Учитывая путь, disk_usage() возвращает именованный кортеж, включая общее, использованное и свободное пространство, выраженное в байтах, плюс процент использования.

Простой пример из документации:

>>> import psutil
>>> psutil.disk_usage('/')
sdiskusage(total=21378641920, used=4809781248, free=15482871808, percent=22.5)

Psutil работает с версиями Python от 2.6 до 3.6 и на Linux, Windows и OSX среди других платформ.

Для первого пункта вы можете попробовать использовать os.path.realpath чтобы получить канонический путь, проверьте его по /etc/mtab (Я бы на самом деле предложил позвонить getmntent, но я не могу найти нормальный способ доступа к нему), чтобы найти самый длинный матч. (чтобы быть уверенным, вы должны, вероятно, stat и файл, и предполагаемая точка монтирования, чтобы убедиться, что они на самом деле находятся на одном устройстве)

Для второго пункта используйте os.statvfs получить размер блока и информацию об использовании.

(Отказ от ответственности: я не проверял ничего из этого, большая часть того, что я знаю, была взята из источников coreutils)

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

11 лет спустя, но расширяя другие ответы.

      import psutil

#File systems
value=psutil.disk_partitions()

for i in value:
    va=i[1]
    value2=psutil.disk_usage(va).percent
    print(value2)
    fs_space[va]=value2

Это добавление его в словарь, захват только процентов, поскольку это то, что мне нужно, но вы можете получить все значения или выбрать нужное из общего, использованного, свободного или процента.

Официальная документация очень помогла

Проверить использование диска на вашем ПК с Windows можно следующим образом:

import psutil

fan = psutil.disk_usage(path="C:/")
print("Available: ", fan.total/1000000000)
print("Used: ", fan.used/1000000000)
print("Free: ", fan.free/1000000000)
print("Percentage Used: ", fan.percent, "%")

Обычно /proc Каталог содержит такую ​​информацию в Linux, это виртуальная файловая система. Например, /proc/mounts дает информацию о текущих смонтированных дисках; и вы можете разобрать его напрямую. Утилиты как top, df все используют /proc,

Я не использовал его, но это также может помочь, если вы хотите обертку: http://bitbucket.org/chrismiles/psi/wiki/Home

Другие вопросы по тегам