3

I can get RAM size okay with ctypes and MEMORYSTATUSEX(), but I'm having trouble finding anything for total disk size (not space available, but total capacity in general).

martineau
  • 119,623
  • 25
  • 170
  • 301
AlwaysQuestioning
  • 1,464
  • 4
  • 24
  • 48

4 Answers4

6

ActiveState has a recipe for this that uses the Windows GetDiskFreeSpaceEx function. It appeared to work when I did some limited testing, however it's has a number of potential issues, so here's a greatly improved and much more bullet-proof version that works in at least Python 2.7+ through 3.x) and uses only built-in modules.

@Eryk Sun deserves most of the credit/blame for the enhancements, since (s)he's obviously an expert on the topic of using ctypes.

import os
import collections
import ctypes
import sys

import locale
locale.setlocale(locale.LC_ALL, '')  # set locale to default to get thousands separators

PULARGE_INTEGER = ctypes.POINTER(ctypes.c_ulonglong)  # Pointer to large unsigned integer
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
kernel32.GetDiskFreeSpaceExW.argtypes = (ctypes.c_wchar_p,) + (PULARGE_INTEGER,) * 3

class UsageTuple(collections.namedtuple('UsageTuple', 'total, used, free')):
    def __str__(self):
        # Add thousands separator to numbers displayed
        return self.__class__.__name__ + '(total={:n}, used={:n}, free={:n})'.format(*self)

def disk_usage(path):
    if sys.version_info < (3,):  # Python 2?
        saved_conversion_mode = ctypes.set_conversion_mode('mbcs', 'strict')
    else:
        try:
            path = os.fsdecode(path)  # allows str or bytes (or os.PathLike in Python 3.6+)
        except AttributeError:  # fsdecode() not added until Python 3.2
            pass

    # Define variables to receive results when passed as "by reference" arguments
    _, total, free = ctypes.c_ulonglong(), ctypes.c_ulonglong(), ctypes.c_ulonglong()

    success = kernel32.GetDiskFreeSpaceExW(
                            path, ctypes.byref(_), ctypes.byref(total), ctypes.byref(free))
    if not success:
        error_code = ctypes.get_last_error()

    if sys.version_info < (3,):  # Python 2?
        ctypes.set_conversion_mode(*saved_conversion_mode)  # restore conversion mode

    if not success:
        windows_error_message = ctypes.FormatError(error_code)
        raise ctypes.WinError(error_code, '{} {!r}'.format(windows_error_message, path))

    used = total.value - free.value
    return UsageTuple(total.value, used, free.value)

if __name__ == '__main__':
    print(disk_usage('C:/'))

Sample output:

UsageTuple(total=102,025,392,128, used=66,308,366,336, free=35,717,025,792)
martineau
  • 119,623
  • 25
  • 170
  • 301
1

Then you should use this code.

import win32com.client as com


def TotalSize(drive):
    """ Return the TotalSize of a shared drive [GB]"""
    try:
        fso = com.Dispatch("Scripting.FileSystemObject")
        drv = fso.GetDrive(drive)
        return drv.TotalSize/2**30
    except:
        return 0

def FreeSpace(drive):
    """ Return the FreeSape of a shared drive [GB]"""
    try:
        fso = com.Dispatch("Scripting.FileSystemObject")
        drv = fso.GetDrive(drive)
        return drv.FreeSpace/2**30
    except:
        return 0

drive = r'C:'
print 'TotalSize of %s = %d GB' % (drive, TotalSize(drive))
print 'FreeSapce on %s = %d GB' % (drive, FreeSapce(drive))

enter image description here

Lex Hobbit
  • 504
  • 1
  • 9
  • 21
1

As of Python 3.3, you can use shutil.disk_usage():

import shutil
print(shutil.disk_usage("E:\\"))

Sample output (where E: is an 8GB SD card):

usage(total=7985954816, used=852361216, free=7133593600)

This has the advantage of working on both Windows and Unix, as well as not needing a 3rd-party library to be installed!

LarsH
  • 27,481
  • 8
  • 94
  • 152
0

you can use psutil, If you want to find total size of your C: drive or any other drive then just provide the path inside disk_usage() function and convert into GB. Here I have found total disk size of C: Drive.

import psutil
totalsize = psutil.disk_usage('C:').total / 2**30
print('totalsize: ',totalsize, ' GB')
M. Paul
  • 361
  • 5
  • 18
  • 1
    I think you should at least mention that [`psutil`](https://pypi.org/project/psutil/) is not in the standard library and must be downloaded and installed. – martineau Sep 17 '20 at 20:58