Cross-platform space remaining on volume using python
Asked Answered
S

12

77

I need a way to determine the space remaining on a disk volume using python on linux, Windows and OS X. I'm currently parsing the output of the various system calls (df, dir) to accomplish this - is there a better way?

Siqueiros answered 9/9, 2008 at 11:36 Comment(1)
See this recipe here: code.activestate.com/recipes/577972-disk-usage/?in=user-4178764Paris
P
79
import ctypes
import os
import platform
import sys

def get_free_space_mb(dirname):
    """Return folder/drive free space (in megabytes)."""
    if platform.system() == 'Windows':
        free_bytes = ctypes.c_ulonglong(0)
        ctypes.windll.kernel32.GetDiskFreeSpaceExW(ctypes.c_wchar_p(dirname), None, None, ctypes.pointer(free_bytes))
        return free_bytes.value / 1024 / 1024
    else:
        st = os.statvfs(dirname)
        return st.f_bavail * st.f_frsize / 1024 / 1024

Note that you must pass a directory name for GetDiskFreeSpaceEx() to work (statvfs() works on both files and directories). You can get a directory name from a file with os.path.dirname().

Also see the documentation for os.statvfs() and GetDiskFreeSpaceEx.

Pre answered 3/3, 2010 at 14:45 Comment(7)
.f_bfree is total number of free blocks in the file system. It should be multiplied by .f_bsize to get number of bytes.Detailed
At least on OS X Lion / Python 2.7 I noticed that multiplying by .f_bsize gives a much too large value as f_bsize is the preferred block size while .f_frsize is the fundamental block size and gives the correct value. On my linux test system both values are identical and thus .f_frsize should work all the time.Knowitall
Works to get available disk on Android Phone, plugged via USB to a Windows system, running the script on Windows. Great.Ileanaileane
@J.F.Sebastian It depends on what you want. It is possible for Linux to reserve space for root. If you want to include this space, use f_bfree. If you want to get the number of blocks available to a user, then use f_bavail. Maybe someone can say if and how quotas are treated?Broccoli
I have three niggles with the above: 1/ The docstring is wrong it returns space in Mbytes & 2/ I never like seeing more than one return statement, (too much time as a tester I guess), so would store the result in a returned value, 3/ Whole MB or decimal MB may make a difference to some people.Excellency
You can also check the platform via sys.platform == 'win32' sys is also available under os! So: os.sys.platform == 'win32'. Down to 2 imports! ;]Magistery
or os.name == 'nt'!Magistery
B
36

Install psutil using pip install psutil. Then you can get the amount of free space in bytes using:

import psutil
print(psutil.disk_usage(".").free)
Bernettabernette answered 29/4, 2015 at 12:43 Comment(3)
Why this is not the best answer?Pehlevi
I think because psutil wasn't always available through pypi.Bernettabernette
I agree this a great answer. I fixed the stale link to psutil. Since disk_usage.free typically returns a huge 64b integer, I suggest you also want to show people disk_usage.percent. psutil.disk_usage(".").percent < 99.9 seems clearer to me...Parody
L
30

You could use the wmi module for windows and os.statvfs for unix

for window

import wmi

c = wmi.WMI ()
for d in c.Win32_LogicalDisk():
    print( d.Caption, d.FreeSpace, d.Size, d.DriveType)

for unix or linux

from os import statvfs

statvfs(path)
Leprose answered 12/10, 2013 at 9:20 Comment(6)
I can't believe how far I had to go down this question to find someone mentioning the WMI. All these crazy people using ctypes to call Windows C APIs directly when they could just use the WMI?Remonaremonetize
@CraigRinger Yes, you are right. We should use the right tool to do the right thing. Most of the common management tasks for window have already been wrapped with win api in wmi. We don't have to remake the wheel. :^DLeprose
Why not psutil handle it?Eveevection
This is why I love stackoverflow. I did not even know about the WMI module and it worked flawlessly.Doykos
@Eveevection yes, that's another good option for handle this task.Leprose
Well, if you want to support vanilla oldschool python 2.7: You need to do these things. The less external dependencies the better. ctypes is built-in! 😐Magistery
C
21

If you're running python3:

Using shutil.disk_usage()with os.path.realpath('/') name-regularization works:

from os import path
from shutil import disk_usage

print([i / 1000000 for i in disk_usage(path.realpath('/'))])

Or

total_bytes, used_bytes, free_bytes = disk_usage(path.realpath('D:\\Users\\phannypack'))

print(total_bytes / 1000000) # for Mb
print(used_bytes / 1000000)
print(free_bytes / 1000000)

giving you the total, used, & free space in MB.

Constitutive answered 1/2, 2018 at 4:52 Comment(2)
Not sure how this isn't the selected answer. Doesn't require using ctypes which can be a hassle going through MSDN docs and ensuring types are coerced correctly.Grained
IMHO this is the best way in this time and age.Draconic
S
10

If you dont like to add another dependency you can for windows use ctypes to call the win32 function call directly.

import ctypes

free_bytes = ctypes.c_ulonglong(0)

ctypes.windll.kernel32.GetDiskFreeSpaceExW(ctypes.c_wchar_p(u'c:\\'), None, None, ctypes.pointer(free_bytes))

if free_bytes.value == 0:
   print 'dont panic'
Sherwood answered 13/11, 2009 at 9:22 Comment(1)
Last few lines: if free_bytes.value == 0: print('dont panic') else: print(free_bytes.value)Nefertiti
I
7

A good cross-platform way is using psutil: http://pythonhosted.org/psutil/#disks (Note that you'll need psutil 0.3.0 or above).

Illconditioned answered 21/7, 2011 at 9:2 Comment(2)
This would be the best answer, but unfortunately psutil is not installable via pip.Dryad
psutil is now available from pypi and most other sources including debian packages.Your
P
6

From Python 3.3 you can use shutil.disk_usage("/").free from standard library for both Windows and UNIX :)

Pyrometallurgy answered 11/8, 2016 at 7:11 Comment(0)
D
4

You can use df as a cross-platform way. It is a part of GNU core utilities. These are the core utilities which are expected to exist on every operating system. However, they are not installed on Windows by default (Here, GetGnuWin32 comes in handy).

df is a command-line utility, therefore a wrapper required for scripting purposes. For example:

from subprocess import PIPE, Popen

def free_volume(filename):
    """Find amount of disk space available to the current user (in bytes) 
       on the file system containing filename."""
    stats = Popen(["df", "-Pk", filename], stdout=PIPE).communicate()[0]
    return int(stats.splitlines()[1].split()[3]) * 1024
Detailed answered 9/9, 2008 at 23:48 Comment(2)
I don't understand why people downvote. For example this answer may be useful to somebody. Anyway it is a good supplement for the other pupe-Pythonic solutions. If anybody doesn't like the answer is no reason to downvote it. As I understand, downvotes are for downright wrong answers. This one is not.Trouper
@Trouper Up vote this answer and It is good know an other way to do the same thing.Leprose
W
1

The os.statvfs() function is a better way to get that information for Unix-like platforms (including OS X). The Python documentation says "Availability: Unix" but it's worth checking whether it works on Windows too in your build of Python (ie. the docs might not be up to date).

Otherwise, you can use the pywin32 library to directly call the GetDiskFreeSpaceEx function.

Whorl answered 9/9, 2008 at 11:40 Comment(1)
os.statvfs() doesn't work on Windows (Python 2.5.2 -- current production version).Detailed
M
1

Below code returns correct value on windows

import win32file    

def get_free_space(dirname):
    secsPerClus, bytesPerSec, nFreeClus, totClus = win32file.GetDiskFreeSpace(dirname)
    return secsPerClus * bytesPerSec * nFreeClus
Mayhap answered 8/3, 2016 at 6:53 Comment(0)
P
0

I Don't know of any cross-platform way to achieve this, but maybe a good workaround for you would be to write a wrapper class that checks the operating system and uses the best method for each.

For Windows, there's the GetDiskFreeSpaceEx method in the win32 extensions.

Pevzner answered 9/9, 2008 at 11:47 Comment(0)
D
0

Most previous answers are correct, I'm using Python 3.10 and shutil. My use case was Windows and C drive only ( but you should be able to extend this for you Linux and Mac as well (here is the documentation)

Here is the example for Windows:

import shutil

total, used, free = shutil.disk_usage("C:/")

print("Total: %d GiB" % (total // (2**30)))
print("Used: %d GiB" % (used // (2**30)))
print("Free: %d GiB" % (free // (2**30)))
Deuce answered 25/7, 2022 at 20:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.