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?
12 Answers
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
.

- 26,737
- 24
- 105
- 146

- 2,679
- 1
- 21
- 18
-
13`.f_bfree` is total number of free blocks in the file system. It should be multiplied by `.f_bsize` to get number of bytes. – jfs Apr 25 '10 at 16:14
-
9At 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. – Dennis Bliefernicht Nov 30 '11 at 08:34
-
1Works to get available disk on Android Phone, plugged via USB to a Windows system, running the script on Windows. Great. – heltonbiker Sep 04 '13 at 17:36
-
@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? – data Nov 11 '13 at 18:44
-
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. – Steve Barnes Jun 06 '14 at 06:05
-
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! ;] – ewerybody Nov 14 '18 at 10:20
-
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)
-
2
-
2
-
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... – smci Jan 08 '19 at 09:15
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)

- 1,786
- 4
- 19
- 33
-
2I 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? – Craig Ringer Apr 23 '15 at 03:51
-
1@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. :^D – Erxin Apr 24 '15 at 02:25
-
-
2This is why I love stackoverflow. I did not even know about the WMI module and it worked flawlessly. – DanGoodrick Mar 15 '16 at 18:18
-
-
1Well, 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! – ewerybody Nov 14 '18 at 10:24
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.

- 5,856
- 4
- 22
- 39
-
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. – pstatix May 05 '21 at 17:08
-
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'

- 1,262
- 11
- 12
-
Last few lines: if free_bytes.value == 0: print('dont panic') else: print(free_bytes.value) – tale852150 Jan 28 '22 at 02:11
From Python 3.3 you can use shutil.disk_usage("/").free from standard library for both Windows and UNIX :)

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

- 12,488
- 6
- 68
- 60

- 61
- 1
- 1
-
This would be the best answer, but unfortunately psutil is not installable via pip. – Gringo Suave Jan 16 '13 at 01:58
-
1psutil is now available from pypi and most other sources including debian packages. – Tully Jan 05 '15 at 22:21
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

- 399,953
- 195
- 994
- 1,670
-
4I 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. – ovgolovin Apr 28 '14 at 19:15
-
@ovgolovin Up vote this answer and It is good know an other way to do the same thing. – Erxin Apr 24 '15 at 03:05
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

- 685
- 2
- 8
- 18
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.

- 30,348
- 12
- 86
- 99

- 951,095
- 183
- 1,149
- 1,285
-
3os.statvfs() doesn't work on Windows (Python 2.5.2 -- current production version). – jfs Sep 29 '08 at 22:33
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.

- 6,787
- 37
- 41
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)))

- 21,260
- 6
- 105
- 81