Найти размер и свободное пространство файловой системы, содержащей данный файл
Я использую Python 2.6 на Linux. Какой самый быстрый способ:
-
чтобы определить, какой раздел содержит данный каталог или файл?
например, предположим, что
/dev/sda2
монтируется на/home
и/dev/mapper/foo
монтируется на/home/foo
. Из строки"/home/foo/bar/baz"
Я хотел бы восстановить пару("/dev/mapper/foo", "home/foo")
. и тогда, чтобы получить статистику использования данного раздела? Например,
/dev/mapper/foo
Я хотел бы получить размер раздела и свободное пространство (в байтах или примерно в мегабайтах).
10 ответов:
Если вам просто нужно свободное пространство на устройстве, см. ответ с помощью
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)
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)
начиная с 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 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)
для первого пункта, вы можете попробовать использовать
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')
что касается второй части вашего вопроса, "получить статистику использования данного раздела", psutil делает это легко с disk_usage (path)
обычно содержит такую информацию в Linux, это виртуальная файловая система. Например,
/proc/mounts
дает информацию о текущих смонтированных дисках; и вы можете проанализировать его напрямую. Утилиты вродеtop
,df
используют/proc
.Я не использовал его, но это тоже может помочь, если вы хотите обертку:http://bitbucket.org/chrismiles/psi/wiki/Home