Python Get File Size of Volumes or Physical Drives

Get hard disk size in Python

For Python 2 till Python 3.3


Notice: As a few people mentioned in the comment section, this solution will work for Python 3.3 and above. For Python 2.7 it is best to use the psutil library, which has a disk_usage function, containing information about total, used and free disk space:

import psutil

hdd = psutil.disk_usage('/')

print ("Total: %d GiB" % hdd.total / (2**30))
print ("Used: %d GiB" % hdd.used / (2**30))
print ("Free: %d GiB" % hdd.free / (2**30))

Python 3.3 and above:

For Python 3.3 and above, you can use the shutil module, which has a disk_usage function, returning a named tuple with the amounts of total, used and free space in your hard drive.

You can call the function as below and get all information about your disk's space:

import shutil

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

print("Total: %d GiB" % (total // (2**30)))
print("Used: %d GiB" % (used // (2**30)))
print("Free: %d GiB" % (free // (2**30)))

Output:

Total: 931 GiB
Used: 29 GiB
Free: 902 GiB

How to get total disk size on Windows?

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)

Getting file size before post with Python

This might help if you want to check size details before saving :

@app.route('/api/uploadJob', methods = ['GET', 'POST'])
def uolpadJob():
try:
if request.method == 'POST':
f = request.files['file']
fullFilePath = os.path.join(app.config['UPLOAD_FOLDER'],
secure_filename(f.filename))
f.seek(0, 2)
file_length = f.tell()
# Introduce your disk space condition and save on basis of that
f.save(fullFilePath)

However if you want to checkup after saving the file to your designated path, then try this :

@app.route('/api/uploadJob', methods = ['GET', 'POST'])
def uolpadJob():
try:
if request.method == 'POST':
f = request.files['file']
fullFilePath = os.path.join(app.config['UPLOAD_FOLDER'],
secure_filename(f.filename))
f.save(fullFilePath)
fileSize = os.stat(fullFilePath).st_size

how to obtain physical drives in Windows

FindFirstVolume and FindNextVolume may be what you need.

MSDN FindFirstVolume page

There's an example that searches for volumes and list all paths for each volume, and at first sight, it seems to allow the possibility that there is no such path for some volumes. That said, I've never used this.

Get Size of Disk and/or Drive With Unknown File Format, C# .NET Framework?

The solution ended up being fairly simple, and an extension from the existing question Getting Disk Size Properly

Posting my solution here, as perhaps the full code will help someone in the future:

(FYI: P/Invoke definitions obtained and minimally modified from http://pinvoke.net)

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CreateFile(
[MarshalAs(UnmanagedType.LPTStr)] string filename,
[MarshalAs(UnmanagedType.U4)] FileAccess access,
[MarshalAs(UnmanagedType.U4)] FileShare share,
IntPtr securityAttributes, // optional SECURITY_ATTRIBUTES struct or IntPtr.Zero
[MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
[MarshalAs(UnmanagedType.U4)] FileAttributes flagsAndAttributes,
IntPtr templateFile);

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern bool DeviceIoControl(IntPtr hDevice, uint dwIoControlCode,
IntPtr lpInBuffer, uint nInBufferSize,
IntPtr lpOutBuffer, uint nOutBufferSize,
out uint lpBytesReturned, IntPtr lpOverlapped);

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool CloseHandle(IntPtr hObject);

struct GET_LENGTH_INFORMATION
{
public long Length;
};
long GetPhysDiskSize(string physDeviceID)
{
uint IOCTL_DISK_GET_LENGTH_INFO = 0x0007405C;
uint dwBytesReturned;

//Example, physDeviceID == @"\\.\PHYSICALDRIVE1"
IntPtr hVolume = CreateFile(physDeviceID, FileAccess.ReadWrite,
FileShare.None, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero);

GET_LENGTH_INFORMATION outputInfo = new GET_LENGTH_INFORMATION();
outputInfo.Length = 0;

IntPtr outBuff = Marshal.AllocHGlobal(Marshal.SizeOf(outputInfo));

bool devIOPass = DeviceIoControl(hVolume,
IOCTL_DISK_GET_LENGTH_INFO,
IntPtr.Zero, 0,
outBuff, (uint)Marshal.SizeOf(outputInfo),
out dwBytesReturned,
IntPtr.Zero);

CloseHandle(hVolume);

outputInfo = (GET_LENGTH_INFORMATION)Marshal.PtrToStructure(outBuff, typeof(GET_LENGTH_INFORMATION));

Marshal.FreeHGlobal(hVolume);
Marshal.FreeHGlobal(outBuff);

return outputInfo.Length;
}


Related Topics



Leave a reply



Submit