Как получить размер диска или блочного устройства в Windows с помощью Python

Как получить размер с блочного устройства или необработанного диска в Windows, если я знаю только имя устройства "\.\PhysicalDrive0" без файловой системы или метки тома?

Я попробовал следующее:

fd = os.open (r "\.\PhysicalDrive0", os.O_RDONLY)

os.lseek (fd, 0, os.SEEK_END)

он отлично работает в Linux, но всегда возвращает "OSError: [Errno 22] Недопустимый аргумент" в Windows.

Я также попробовал ctypes.windll.kernel32.GetDiskFreeSpaceExW(), но, похоже, он работает только для диска с файловой системой и назначенной меткой тома.

Как правильно сделать это для необработанного диска или блочного устройства?

Заранее спасибо.

2 ответа

С использованием wmi модуль

import wmi
c = wmi.WMI()
[drive] = c.Win32_DiskDrive(Index=0)
print("The disk has %s bytes" % drive.size)
print("Or %s GB" % int(int(drive.size) / 1024**3))

The disk has 320070320640 bytes
Or 298 GB

Этот код запрашивает интерфейс WMI для Win32_DiskDrive объекты с индексом, равным 0 (так что есть только один результат, и этот результат PHYSICALDRIVE0). drive объект имеет атрибут с именем size, которая является строкой, содержащей размер диска в байтах.

У меня есть решение.. но это не красиво. Используйте diskpart. К сожалению, он не дает вам точный размер байта, если это необходимо, но он дает вам удобочитаемую строку.

import tempfile
import subprocess
import re
import os

def query_diskpart(command):
    """Run command script for diskpart.

    Args:
        command(str): String of all commands to run against diskpart
    Returns:
        String of all diskpart standard output
    Size Effects:
        Creates a temporary file(and then deletes it)
        Creates a subprocess to run diskpart
    """
    with tempfile.NamedTemporaryFile(mode='w', delete=False) as temp_handle:
        temp_handle.write(command)
    # The temporary file needs to be closed before opening with diskpart
    diskpart_handle = subprocess.Popen(["diskpart", '/s', temp_handle.name], stdout=subprocess.PIPE)
    output, _ = diskpart_handle.communicate()

    os.remove(temp_handle.name)
    return output

def match_drive_size(diskpart_output, disk_num):
    """Get drive size from diskpart output.

    Args:
        diskpart_output(str): String of diskpart standard output
        disk_num(int): Number of PhysicalDrive to match against
    Returns:
        Human readable size of drive.
    Raises:
        ValueError if drive doesn't exist.
        """

    # Break up gigantic output string
    output_lines = diskpart_output.decode().split(os.linesep)
    # Apply regular expression to every line, but it should only match one
    matches = [re.match(".*Disk %s\s*(.*)" % disk_num, line) for line in output_lines]
    size = None
    for match in matches:
        if match:
            # Get first subgroup (parens above)
            size_line = match.group(1)
            # Split by whitespace
            size_list = re.split("\s*", size_line)
            # Merge numerical value + units
            # ['256', 'GB'] becomes 256GB
            size = ''.join(size_list[1:3])
            break
    else:
        raise ValueError("PHYSICALDRIVE%s does not exist", disk_num)
    return size

def get_drive_size(disk_num):
    """Get Windows Drive size.

    Args:
        disk_num(int): The Physical Drive Number
            e.g. for PHYSICALDRIVE0 put 0
    Returns:
        Human readable string of the drive size
    """
    output = query_diskpart("list disk\n")
    drive_size = match_drive_size(output, disk_num)
    return drive_size

if __name__ == "__main__":
    print(get_drive_size(0))
Другие вопросы по тегам