76

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 Answers12

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.

Martin Tournoij
  • 26,737
  • 24
  • 105
  • 146
Frankovskyi Bogdan
  • 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
  • 9
    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. – Dennis Bliefernicht Nov 30 '11 at 08:34
  • 1
    Works 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
  • or `os.name == 'nt'`! – ewerybody Nov 14 '18 at 10:28
34

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)
smci
  • 32,567
  • 20
  • 113
  • 146
jhasse
  • 2,379
  • 1
  • 30
  • 40
  • 2
    Why this is not the best answer? – jayatubi Jun 01 '16 at 03:35
  • 2
    I think because psutil wasn't always available through pypi. – jhasse Jun 01 '16 at 08:01
  • 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
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)
Erxin
  • 1,786
  • 4
  • 19
  • 33
  • 2
    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? – 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
  • Why not `psutil` handle it? – Fr0zenFyr Nov 21 '15 at 12:03
  • 2
    This 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
  • @Fr0zenFyr yes, that's another good option for handle this task. – Erxin Sep 30 '16 at 08:08
  • 1
    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! – ewerybody Nov 14 '18 at 10:24
18

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.

Rob Truxal
  • 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
  • IMHO this is the best way in this time and age. – phoibos Aug 31 '21 at 12:39
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'
Stefan Lundström
  • 1,262
  • 11
  • 12
6

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

Mišo
  • 2,327
  • 1
  • 23
  • 25
6

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

Giampaolo Rodolà
  • 12,488
  • 6
  • 68
  • 60
Yuriy
  • 61
  • 1
  • 1
3

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
jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • 4
    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. – 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
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
Sanjay Bhosale
  • 685
  • 2
  • 8
  • 18
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.

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

hasseg
  • 6,787
  • 37
  • 41
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)))
grepit
  • 21,260
  • 6
  • 105
  • 81